/**
 * function-palette.mjs — AI-Do v4.0 Function Palette (Skills)
 * Renders skill cards in the right panel grouped by category,
 * skill detail popovers, and the full skills view (#view-skills).
 */

import store from '../store.mjs';
import eventBus, { EVENTS } from '../event-bus.mjs';
import api from '../api.mjs';
import { $, createElement, icon, empty } from '../utils/dom.mjs';
import { relativeTime, truncate } from '../utils/format.mjs';

// ── Category → icon mapping ──
const CATEGORY_ICONS = {
  Search: 'search',
  Retrieve: 'retrieve',
  Analyze: 'analyze',
  Create: 'create',
  Configure: 'configure',
  Visualize: 'vision',
  Journal: 'journal',
  Evolve: 'evolve'
};

// ── Category display order ──
const CATEGORY_ORDER = ['Search', 'Retrieve', 'Analyze', 'Create', 'Configure', 'Visualize', 'Journal', 'Evolve'];

// ── DOM references ──
let panelContent = null;
let fullViewEl = null;
let activePopover = null;
let recentExecutions = [];

// ──────────────────────────────────────
// Public init
// ──────────────────────────────────────

export function init() {
  panelContent = $('.right-panel-content');
  fullViewEl = $('#view-skills');

  if (!panelContent) {
    console.warn('[function-palette] .right-panel-content not found');
    return;
  }

  // Bind toggle button
  const toggleBtn = $('.right-panel-toggle');
  if (toggleBtn) {
    toggleBtn.addEventListener('click', () => {
      store.dispatch('TOGGLE_RIGHT_PANEL');
    });
  }

  // Subscribe to palette data
  store.subscribe(
    (s) => s.skills.palette,
    (palette) => {
      renderPalette(palette);
      if (fullViewEl) renderFullView(palette);
    }
  );

  // Subscribe to running skill
  store.subscribe(
    (s) => s.skills.running,
    (running) => {
      updateRunningState(running);
    }
  );

  // Track recent executions
  eventBus.on(EVENTS.SKILL_START, (data) => {
    if (data?.name) {
      recentExecutions.unshift({
        name: data.name,
        timestamp: Date.now(),
        status: 'running'
      });
      recentExecutions = recentExecutions.slice(0, 20);
      updateRecentSection();
    }
  });

  eventBus.on(EVENTS.SKILL_COMPLETE, (data) => {
    if (data?.name) {
      const entry = recentExecutions.find(
        (e) => e.name === data.name && e.status === 'running'
      );
      if (entry) {
        entry.status = data.success !== false ? 'success' : 'failed';
        entry.completedAt = Date.now();
      }
      updateRecentSection();
    }
  });

  // Close popover on outside click
  document.addEventListener('click', handleOutsideClick);

  // Initial render with current data
  const palette = store.getState().skills.palette;
  if (palette && palette.length > 0) {
    renderPalette(palette);
    if (fullViewEl) renderFullView(palette);
  } else {
    renderEmptyState();
  }

  // Build the full view shell if the element exists
  if (fullViewEl) {
    buildFullViewShell();
  }
}

// ──────────────────────────────────────
// Right Panel Rendering
// ──────────────────────────────────────

function renderPalette(palette) {
  if (!panelContent) return;

  // Dismiss any open popover
  dismissPopover();

  empty(panelContent);

  if (!palette || palette.length === 0) {
    renderEmptyState();
    return;
  }

  const groups = groupByCategory(palette);

  for (const category of CATEGORY_ORDER) {
    const skills = groups[category];
    if (!skills || skills.length === 0) continue;

    const categoryEl = buildCategoryGroup(category, skills);
    panelContent.appendChild(categoryEl);
  }

  // Render any remaining categories not in CATEGORY_ORDER
  for (const [category, skills] of Object.entries(groups)) {
    if (CATEGORY_ORDER.includes(category)) continue;
    const categoryEl = buildCategoryGroup(category, skills);
    panelContent.appendChild(categoryEl);
  }

  // Apply running state if any
  const running = store.getState().skills.running;
  if (running) {
    updateRunningState(running);
  }
}

function renderEmptyState() {
  if (!panelContent) return;
  empty(panelContent);

  const emptyEl = createElement('div', { className: 'skill-palette-empty' });
  emptyEl.appendChild(icon('skills', { size: 40 }));
  emptyEl.appendChild(createElement('p', {}, ['No functions available yet. Skills will appear here as they are loaded.']));
  panelContent.appendChild(emptyEl);
}

function buildCategoryGroup(category, skills) {
  const group = createElement('div', { className: 'skill-category' });

  // Category header
  const header = createElement('div', { className: 'skill-category-header' });
  const iconName = CATEGORY_ICONS[category] || 'skills';
  header.appendChild(icon(iconName, { size: 14 }));
  header.appendChild(createElement('span', { className: 'skill-category-label' }, [category]));
  group.appendChild(header);

  // Skill cards list
  const list = createElement('div', { className: 'skill-category-list' });
  for (const skill of skills) {
    const card = buildSkillCard(skill);
    list.appendChild(card);
  }
  group.appendChild(list);

  return group;
}

function buildSkillCard(skill) {
  const card = createElement('div', {
    className: 'skill-card',
    dataset: {
      category: skill.category || 'Create',
      skill: skill.name
    }
  });

  // Icon circle
  const iconCircle = createElement('div', { className: 'skill-card-icon' });
  const iconName = skill.icon || CATEGORY_ICONS[skill.category] || 'skills';
  iconCircle.appendChild(icon(iconName, { size: 16 }));
  card.appendChild(iconCircle);

  // Info area
  const info = createElement('div', { className: 'skill-card-info' });
  info.appendChild(createElement('div', { className: 'skill-card-name' }, [skill.displayName || skill.name]));
  info.appendChild(createElement('div', { className: 'skill-card-desc' }, [truncate(skill.description || '', 60)]));
  card.appendChild(info);

  // Click to show detail popover
  card.addEventListener('click', (e) => {
    e.stopPropagation();
    showPopover(skill);
  });

  return card;
}

// ──────────────────────────────────────
// Running State
// ──────────────────────────────────────

function updateRunningState(runningName) {
  // Right panel cards
  if (panelContent) {
    const cards = panelContent.querySelectorAll('.skill-card');
    for (const card of cards) {
      const isRunning = card.dataset.skill === runningName;
      card.classList.toggle('running', isRunning);
    }
  }

  // Full view rows
  if (fullViewEl) {
    const rows = fullViewEl.querySelectorAll('.skill-full-row');
    for (const row of rows) {
      const isRunning = row.dataset.skill === runningName;
      row.classList.toggle('running', isRunning);
    }
  }
}

// ──────────────────────────────────────
// Skill Detail Popover
// ──────────────────────────────────────

function showPopover(skill) {
  dismissPopover();

  const panel = $('.right-panel');
  if (!panel) return;

  // Ensure panel has relative positioning for the absolute popover
  if (getComputedStyle(panel).position === 'static') {
    panel.style.position = 'relative';
  }

  const popover = createElement('div', { className: 'skill-detail' });

  // Close button
  const closeBtn = createElement('button', {
    className: 'skill-detail-close',
    'aria-label': 'Close detail'
  });
  closeBtn.appendChild(icon('close', { size: 14 }));
  closeBtn.addEventListener('click', (e) => {
    e.stopPropagation();
    dismissPopover();
  });
  popover.appendChild(closeBtn);

  // Icon
  const detailIcon = createElement('div', { className: 'skill-detail-icon' });
  const category = skill.category || 'Create';
  // Apply inline gradient matching the category
  const gradients = {
    Search: 'linear-gradient(135deg, #60a5fa, #3b82f6)',
    Retrieve: 'linear-gradient(135deg, #34d399, #10b981)',
    Analyze: 'linear-gradient(135deg, #fbbf24, #f59e0b)',
    Create: 'linear-gradient(135deg, #a78bfa, #8b5cf6)',
    Configure: 'linear-gradient(135deg, #f472b6, #ec4899)',
    Visualize: 'linear-gradient(135deg, #2dd4bf, #14b8a6)',
    Journal: 'linear-gradient(135deg, #fb923c, #f97316)',
    Evolve: 'linear-gradient(135deg, #e879f9, #d946ef)'
  };
  detailIcon.style.background = gradients[category] || gradients.Create;
  const iconName = skill.icon || CATEGORY_ICONS[category] || 'skills';
  detailIcon.appendChild(icon(iconName, { size: 24 }));
  popover.appendChild(detailIcon);

  // Name
  popover.appendChild(
    createElement('div', { className: 'skill-detail-name' }, [skill.displayName || skill.name])
  );

  // Category badge
  const catBadge = createElement('div', { className: 'skill-detail-category' });
  catBadge.appendChild(icon(CATEGORY_ICONS[category] || 'skills', { size: 12 }));
  catBadge.appendChild(document.createTextNode(category));
  popover.appendChild(catBadge);

  // Full description
  popover.appendChild(
    createElement('div', { className: 'skill-detail-desc' }, [skill.description || 'No description available.'])
  );

  // Parameter input
  const placeholders = {
    Search: 'What to search for...',
    Retrieve: 'URL, file path, or text to ingest...',
    Analyze: 'What to analyze...',
    Create: 'What should be built...',
    Configure: 'What to configure...',
    Visualize: 'What to visualize...',
    Journal: 'Journal topic or prompt...',
    Evolve: 'What to improve...'
  };
  const inputEl = createElement('input', {
    type: 'text',
    className: 'skill-detail-input glass-input',
    placeholder: placeholders[category] || `Describe what to do...`
  });
  inputEl.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      runSkill(skill.name, inputEl.value.trim());
      dismissPopover();
    }
  });
  inputEl.addEventListener('click', (e) => e.stopPropagation());
  popover.appendChild(inputEl);

  // Run button area
  const actions = createElement('div', { className: 'skill-detail-actions' });
  const runBtn = createElement('button', { className: 'skill-detail-run' });
  runBtn.appendChild(icon('play', { size: 16 }));
  runBtn.appendChild(document.createTextNode('Run'));

  runBtn.addEventListener('click', (e) => {
    e.stopPropagation();
    runSkill(skill.name, inputEl.value.trim());
    dismissPopover();
  });

  actions.appendChild(runBtn);
  popover.appendChild(actions);

  panel.appendChild(popover);
  activePopover = popover;
}

function dismissPopover() {
  if (activePopover) {
    activePopover.remove();
    activePopover = null;
  }
}

function handleOutsideClick(e) {
  if (!activePopover) return;

  const panel = $('.right-panel');
  // If click is outside the right panel, dismiss
  if (panel && !panel.contains(e.target)) {
    dismissPopover();
  }
}

// ──────────────────────────────────────
// Run Skill
// ──────────────────────────────────────

function runSkill(skillName, userInput) {
  // Always include skill name so the classifier can detect it.
  // If user provided input, prepend with skill context; otherwise generic.
  const message = userInput
    ? `[${skillName}] ${userInput}`
    : `Run the ${skillName} skill`;
  api.post('/api/chat', { message }).catch((err) => {
    console.error('[function-palette] Failed to run skill:', err);
  });

  // Switch to chat view so user sees the response
  store.dispatch('SET_VIEW', 'chat');

  // Expand sidebar if collapsed so user can see the conversation
  if (store.getState().ui.sidebarCollapsed) {
    store.dispatch('TOGGLE_SIDEBAR');
  }

  // On mobile/tablet, close the right panel overlay
  const rightPanel = document.querySelector('.right-panel');
  if (rightPanel) rightPanel.classList.remove('open');

  const backdrop = document.querySelector('.panel-backdrop');
  if (backdrop) backdrop.classList.remove('active');
}

// ──────────────────────────────────────
// Full View (#view-skills)
// ──────────────────────────────────────

function buildFullViewShell() {
  if (!fullViewEl) return;
  empty(fullViewEl);

  const wrapper = createElement('div', { className: 'skills-full-view' });

  // Header
  const header = createElement('div', { className: 'skills-full-header' });
  header.appendChild(createElement('h2', {}, ['Skills & Functions']));

  const refreshBtn = createElement('button', {
    className: 'glass-button-icon',
    'aria-label': 'Refresh skills'
  });
  refreshBtn.appendChild(icon('refresh', { size: 18 }));
  refreshBtn.addEventListener('click', () => {
    api.getSkillsPalette()
      .then((palette) => store.dispatch('SET_SKILL_PALETTE', palette))
      .catch((err) => console.error('[function-palette] Refresh failed:', err));
  });
  header.appendChild(refreshBtn);
  wrapper.appendChild(header);

  // Body
  const body = createElement('div', { className: 'skills-full-body' });
  body.setAttribute('data-skills-body', 'true');
  wrapper.appendChild(body);

  fullViewEl.appendChild(wrapper);

  // Render with current data
  const palette = store.getState().skills.palette;
  if (palette && palette.length > 0) {
    renderFullViewContent(body, palette);
  }
}

function renderFullView(palette) {
  if (!fullViewEl) return;
  const body = fullViewEl.querySelector('[data-skills-body]');
  if (!body) return;

  renderFullViewContent(body, palette);
}

function renderFullViewContent(body, palette) {
  empty(body);

  if (!palette || palette.length === 0) {
    body.appendChild(
      createElement('div', { className: 'skill-palette-empty' }, [
        createElement('p', {}, ['No skills loaded yet.'])
      ])
    );
    return;
  }

  const grid = createElement('div', { className: 'skills-full-grid' });
  const groups = groupByCategory(palette);
  const running = store.getState().skills.running;

  for (const category of CATEGORY_ORDER) {
    const skills = groups[category];
    if (!skills || skills.length === 0) continue;

    const catEl = buildFullCategoryGroup(category, skills, running);
    grid.appendChild(catEl);
  }

  // Any remaining categories
  for (const [category, skills] of Object.entries(groups)) {
    if (CATEGORY_ORDER.includes(category)) continue;
    const catEl = buildFullCategoryGroup(category, skills, running);
    grid.appendChild(catEl);
  }

  body.appendChild(grid);

  // Recent executions section
  const recentSection = createElement('div', {
    className: 'skills-recent-section',
    dataset: { recentSection: 'true' }
  });
  recentSection.appendChild(createElement('div', { className: 'skills-recent-title' }, ['Recent Executions']));

  const recentList = createElement('div', { className: 'skills-recent-list' });
  recentList.setAttribute('data-recent-list', 'true');

  if (recentExecutions.length === 0) {
    recentList.appendChild(createElement('div', { className: 'skills-recent-empty' }, ['No recent skill executions.']));
  } else {
    for (const entry of recentExecutions.slice(0, 10)) {
      recentList.appendChild(buildRecentItem(entry));
    }
  }

  recentSection.appendChild(recentList);
  body.appendChild(recentSection);
}

function buildFullCategoryGroup(category, skills, running) {
  const group = createElement('div', { className: 'skills-full-category' });

  // Category header
  const header = createElement('div', { className: 'skills-full-category-header' });
  const iconName = CATEGORY_ICONS[category] || 'skills';
  header.appendChild(icon(iconName, { size: 16 }));
  header.appendChild(createElement('span', {}, [category]));
  group.appendChild(header);

  // Skill rows
  for (const skill of skills) {
    const row = buildFullSkillRow(skill, running);
    group.appendChild(row);
  }

  return group;
}

function buildFullSkillRow(skill, running) {
  const isRunning = running === skill.name;
  const category = skill.category || 'Create';

  const row = createElement('div', {
    className: `skill-full-row${isRunning ? ' running' : ''}`,
    dataset: {
      category,
      skill: skill.name
    }
  });

  // Icon
  const rowIcon = createElement('div', { className: 'skill-full-row-icon' });
  const iconName = skill.icon || CATEGORY_ICONS[category] || 'skills';
  rowIcon.appendChild(icon(iconName, { size: 18 }));
  row.appendChild(rowIcon);

  // Info
  const info = createElement('div', { className: 'skill-full-row-info' });
  info.appendChild(createElement('div', { className: 'skill-full-row-name' }, [skill.displayName || skill.name]));
  info.appendChild(createElement('div', { className: 'skill-full-row-desc' }, [skill.description || '']));
  row.appendChild(info);

  // Toggle switch
  const toggleWrap = createElement('div', { className: 'skill-full-row-toggle' });
  const isEnabled = skill.enabled !== false;
  const toggle = createElement('button', {
    className: `toggle${isEnabled ? ' active' : ''}`,
    'aria-label': `Toggle ${skill.displayName || skill.name}`,
    role: 'switch',
    'aria-checked': String(isEnabled)
  });
  toggle.addEventListener('click', async (e) => {
    e.stopPropagation();
    const newEnabled = !toggle.classList.contains('active');
    try {
      await api.toggleSkill(skill.name, newEnabled);
      toggle.classList.toggle('active', newEnabled);
      toggle.setAttribute('aria-checked', String(newEnabled));
    } catch (err) {
      console.error('[function-palette] Toggle failed:', err);
      eventBus.emit(EVENTS.NOTIFICATION, {
        message: `Failed to toggle ${skill.displayName || skill.name}`,
        type: 'error'
      });
    }
  });
  toggleWrap.appendChild(toggle);
  row.appendChild(toggleWrap);

  // Click to run
  row.addEventListener('click', () => {
    runSkill(skill.name);
  });

  return row;
}

// ──────────────────────────────────────
// Recent Executions
// ──────────────────────────────────────

function buildRecentItem(entry) {
  const item = createElement('div', { className: 'skills-recent-item' });

  // Status dot
  const dot = createElement('div', {
    className: `skills-recent-item-status ${entry.status === 'running' ? '' : entry.status}`
  });
  if (entry.status === 'running') {
    dot.style.background = 'var(--accent-primary-light)';
    dot.style.animation = 'statusBlink 1.2s ease-in-out infinite';
  }
  item.appendChild(dot);

  // Name
  item.appendChild(createElement('span', { className: 'skills-recent-item-name' }, [entry.name]));

  // Time
  const ts = entry.completedAt || entry.timestamp;
  item.appendChild(createElement('span', { className: 'skills-recent-item-time' }, [relativeTime(ts)]));

  return item;
}

function updateRecentSection() {
  if (!fullViewEl) return;

  const list = fullViewEl.querySelector('[data-recent-list]');
  if (!list) return;

  empty(list);

  if (recentExecutions.length === 0) {
    list.appendChild(createElement('div', { className: 'skills-recent-empty' }, ['No recent skill executions.']));
  } else {
    for (const entry of recentExecutions.slice(0, 10)) {
      list.appendChild(buildRecentItem(entry));
    }
  }
}

// ──────────────────────────────────────
// Helpers
// ──────────────────────────────────────

function groupByCategory(palette) {
  const groups = {};
  for (const skill of palette) {
    const cat = skill.category || 'Create';
    if (!groups[cat]) groups[cat] = [];
    groups[cat].push(skill);
  }
  return groups;
}
