import type { DimSdkStore } from '#cli/core/store'
import type { ComputedRef, Ref } from 'vue'
import type { DimSdkCommandPaletteCommand } from '../../utils/command-palette'
import { t } from '#cli/i18n'
import { computed } from 'vue'
import { createDimSdkBaseCommands } from '../../utils/command-palette'

const RECENT_COMMANDS_LIMIT = 5

type CommandOption = Readonly<{ label: string; detail?: string }>

type UseChatCommandsOptions = Readonly<{
  store: DimSdkStore
  nodeLike: boolean
  isCustomProvider: ComputedRef<boolean>
  showCommands: Ref<boolean>
  closeCommandPalette: () => void
  openSessionsDialog: () => void
  openTimeline: () => void
  openSessionTrace: () => void
  createNewSession: () => void
  openHelp: () => void
  openCustomSettingsCommand: () => void
  openLanguage: () => void
  openToolApprovals: () => void
  openMcpSettings: () => void
  openPlugins: () => void
  openConnect: () => void
  openModels: () => void
  openTheme: () => void
}>

export function useChatCommands(opts: UseChatCommandsOptions): Readonly<{
  commandOptions: ComputedRef<readonly CommandOption[]>
  onCommandSelect: (v: string | null) => void
  recordRecentCommand: (label: string) => void
}> {
  const recordRecentCommand = (label: string) => {
    const text = String(label ?? '').trim()
    if (!text) return
    const current = Array.isArray(opts.store.state.ui.recentCommands)
      ? opts.store.state.ui.recentCommands
      : []
    const next = [text, ...current.filter((v) => v !== text)].slice(
      0,
      RECENT_COMMANDS_LIMIT,
    )
    opts.store.state.ui.recentCommands = next
  }

  const commands = computed<readonly DimSdkCommandPaletteCommand[]>(() => [
    ...createDimSdkBaseCommands({
      openSessionsDialog: opts.openSessionsDialog,
      openTimeline: opts.openTimeline,
      openTrace: opts.openSessionTrace,
      createNewSession: opts.createNewSession,
      openHelp: opts.openHelp,
      openConfig: opts.openCustomSettingsCommand,
      openLanguage: opts.openLanguage,
      openToolApprovals: opts.openToolApprovals,
      openMcpSettings: opts.openMcpSettings,
      openPlugins: opts.openPlugins,
      openConnect: opts.openConnect,
      openModels: opts.openModels,
      includeSettings: true,
      includeNewSession: false,
      includeHelp: false,
    }),
    {
      label: t('chatPage.commands.themeLabel'),
      detail: t('chatPage.commands.themeDetail'),
      run: () => opts.openTheme(),
    },
  ])

  const recentCommands = computed(() => {
    const recent = Array.isArray(opts.store.state.ui.recentCommands)
      ? opts.store.state.ui.recentCommands
      : []
    const byLabel = new Map(commands.value.map((c) => [c.label, c] as const))
    return recent
      .map((label) => byLabel.get(label))
      .filter(Boolean) as DimSdkCommandPaletteCommand[]
  })

  const commandPaletteCommands = computed(() => {
    const recent = recentCommands.value
    if (recent.length === 0) return commands.value
    const recentLabels = new Set(recent.map((c) => c.label))
    const rest = commands.value.filter((c) => !recentLabels.has(c.label))
    return [...recent, ...rest]
  })

  const commandOptions = computed(() => {
    if (!opts.showCommands.value) return []
    return commandPaletteCommands.value.map((c) => ({
      label: c.label,
      detail: c.detail,
    }))
  })

  function onCommandSelect(v: string | null): void {
    opts.closeCommandPalette()
    if (!v) return
    recordRecentCommand(v)
    const cmd = commandPaletteCommands.value.find((c) => c.label === v)
    cmd?.run()
  }

  return {
    commandOptions,
    onCommandSelect,
    recordRecentCommand,
  }
}
