/*
 *  CommandPalette.tsx
 *  Zyquo Cloud Web
 *
 *  Author: Simon-Pierre Boucher
 *  Mail: contact@spboucher.ai
 *
 *  ⌘K command palette — everything in one place: actions (new chat, switch
 *  model, compare, settings, focus mode, summarize), jump to conversation,
 *  apply persona, insert template, switch model. Keyboard-driven.
 */

import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'
import { CATALOG } from '../features/catalogHelpers'
import { PERSONAS } from '../features/personasData'
import { PROMPT_TEMPLATES } from '../features/promptLibraryData'
import { summarizeConversation } from '../features/conversationTools'
import { PROVIDER_META } from '../providers/registry'
import { uid, useStore } from '../state/store'
import { contextBadge, type AIModel } from '../types'
import {
  IconColumns,
  IconCommand,
  IconDoc,
  IconGear,
  IconLightbulb,
  IconPlus,
  IconSearch,
  ProviderGlyph,
} from './icons'

interface PaletteItem {
  id: string
  section: string
  icon: ReactNode
  title: string
  subtitle?: string
  run: () => void
}

export default function CommandPalette({ onClose }: { onClose: () => void }) {
  const [query, setQuery] = useState('')
  const [highlight, setHighlight] = useState(0)
  const inputRef = useRef<HTMLInputElement>(null)
  const conversations = useStore((s) => s.conversations)
  const selectedID = useStore((s) => s.selectedID)

  useEffect(() => inputRef.current?.focus(), [])

  const items: PaletteItem[] = useMemo(() => {
    const state = useStore.getState()
    const q = query.toLowerCase().trim()
    const match = (...targets: (string | undefined)[]) =>
      q === '' || targets.some((t) => t?.toLowerCase().includes(q))

    const out: PaletteItem[] = []

    // Actions
    const actions: PaletteItem[] = [
      {
        id: 'act-new',
        section: 'Actions',
        icon: <IconPlus size={12} />,
        title: 'New chat',
        subtitle: '⌘N',
        run: () => state.newConversation(),
      },
      {
        id: 'act-compare',
        section: 'Actions',
        icon: <IconColumns size={12} />,
        title: 'Compare models…',
        run: () => state.setCompareOpen(true),
      },
      {
        id: 'act-model',
        section: 'Actions',
        icon: <IconCommand size={12} />,
        title: 'Switch model…',
        run: () => state.setModelMenuOpen(true),
      },
      {
        id: 'act-settings',
        section: 'Actions',
        icon: <IconGear size={12} />,
        title: 'Open Settings',
        subtitle: '⌘,',
        run: () => state.openSettings(),
      },
      {
        id: 'act-focus',
        section: 'Actions',
        icon: <IconCommand size={12} />,
        title: state.settings.focusMode ? 'Exit focus mode' : 'Focus mode',
        run: () => state.updateSettings({ focusMode: !state.settings.focusMode }),
      },
      ...(selectedID
        ? [
            {
              id: 'act-summarize',
              section: 'Actions',
              icon: <IconDoc size={12} />,
              title: 'Summarize this conversation',
              run: () => void summarizeConversation(selectedID),
            },
            {
              id: 'act-duplicate',
              section: 'Actions',
              icon: <IconCopyIconFallback />,
              title: 'Duplicate this conversation',
              run: () => {
                const conversation = state.conversations.find((c) => c.id === selectedID)
                if (!conversation) return
                state.restoreConversation({
                  ...conversation,
                  id: uid(),
                  title: `${conversation.title} (copy)`,
                  messages: conversation.messages.map((m) => ({ ...m, id: uid() })),
                  createdAt: Date.now(),
                  updatedAt: Date.now(),
                  pinned: false,
                })
              },
            },
          ]
        : []),
    ]
    out.push(...actions.filter((a) => match(a.title)))

    // Conversations
    out.push(
      ...conversations
        .filter((c) => match(c.title))
        .slice(0, 6)
        .map((c) => ({
          id: `conv-${c.id}`,
          section: 'Conversations',
          icon: <IconSearch size={12} />,
          title: c.title,
          subtitle: c.modelID,
          run: () => state.select(c.id),
        }))
    )

    // Models
    const models = (q === '' ? CATALOG.filter((m) => m.isRecommended) : CATALOG).filter((m) =>
      match(m.displayName, m.id, PROVIDER_META[m.provider].displayName)
    )
    out.push(
      ...models.slice(0, 8).map((m: AIModel) => ({
        id: `model-${m.provider}-${m.id}`,
        section: 'Models',
        icon: <ProviderGlyph provider={m.provider} size={12} />,
        title: m.displayName,
        subtitle: `${PROVIDER_META[m.provider].displayName} · ${contextBadge(m)}`,
        run: () => {
          if (state.selectedID) {
            state.updateConversation(state.selectedID, { modelID: m.id, provider: m.provider })
          } else {
            state.newConversation({ model: m })
          }
        },
      }))
    )

    // Personas
    out.push(
      ...PERSONAS.filter((p) => match(p.name, p.systemPrompt))
        .slice(0, 6)
        .map((p) => ({
          id: `persona-${p.id}`,
          section: 'Personas',
          icon: <IconLightbulb size={12} />,
          title: p.name,
          subtitle: p.systemPrompt.slice(0, 70),
          run: () => {
            if (state.selectedID) {
              state.updateConversation(state.selectedID, {
                systemPrompt: p.systemPrompt,
                personaID: p.id,
              })
            } else {
              state.newConversation({ systemPrompt: p.systemPrompt, personaID: p.id })
            }
            state.toast(`Persona: ${p.name}`, 'success')
          },
        }))
    )

    // Templates
    out.push(
      ...PROMPT_TEMPLATES.filter((t) => match(t.title, t.category))
        .slice(0, 10)
        .map((t) => ({
          id: `tpl-${t.id}`,
          section: 'Prompt Library',
          icon: <IconDoc size={12} />,
          title: t.title,
          subtitle: t.category,
          run: () => {
            if (!state.selectedID) state.newConversation()
            state.setDraftSeed(t.body.replace('{{input}}', ''))
          },
        }))
    )

    return out
  }, [query, conversations, selectedID])

  useEffect(() => setHighlight(0), [query])

  const runItem = (item: PaletteItem) => {
    onClose()
    item.run()
  }

  const onKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === 'ArrowDown') {
      e.preventDefault()
      setHighlight((h) => Math.min(h + 1, items.length - 1))
    } else if (e.key === 'ArrowUp') {
      e.preventDefault()
      setHighlight((h) => Math.max(h - 1, 0))
    } else if (e.key === 'Enter') {
      e.preventDefault()
      const item = items[highlight]
      if (item) runItem(item)
    } else if (e.key === 'Escape') {
      onClose()
    }
  }

  let lastSection = ''
  return (
    <div className="overlay" onMouseDown={(e) => e.target === e.currentTarget && onClose()}>
      <div className="panel" style={{ width: 560 }} onKeyDown={onKeyDown}>
        <div className="panel-search">
          <IconCommand size={14} />
          <input
            ref={inputRef}
            placeholder="Switch model, run template, jump to chat…"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
          />
        </div>
        <div className="panel-list" style={{ maxHeight: 380 }}>
          {items.length === 0 && <div className="panel-empty">Nothing matches.</div>}
          {items.map((item, index) => {
            const header =
              item.section !== lastSection ? (
                <div className="panel-section-header" key={`h-${item.section}`}>
                  {item.section}
                </div>
              ) : null
            lastSection = item.section
            return (
              <div key={item.id}>
                {header}
                <button
                  className={`model-row${index === highlight ? ' highlighted' : ''}`}
                  onClick={() => runItem(item)}
                  onMouseMove={() => setHighlight(index)}
                >
                  <span className="glyph">{item.icon}</span>
                  <span className="model-row-name">{item.title}</span>
                  {item.subtitle && (
                    <span className="model-row-provider" style={{ marginLeft: 'auto' }}>
                      {item.subtitle.length > 46 ? `${item.subtitle.slice(0, 46)}…` : item.subtitle}
                    </span>
                  )}
                </button>
              </div>
            )
          })}
        </div>
        <div className="panel-footer">
          <span>
            <kbd>↑↓</kbd> navigate
          </span>
          <span>
            <kbd>↵</kbd> run
          </span>
          <span>
            <kbd>esc</kbd> close
          </span>
        </div>
      </div>
    </div>
  )
}

function IconCopyIconFallback() {
  return <IconDoc size={12} />
}
