import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { skillApi, type Skill, type SkillCreate } from '@/api/skill'

function prefersReducedMotion() {
  return typeof window !== 'undefined'
    && typeof window.matchMedia === 'function'
    && window.matchMedia('(prefers-reduced-motion: reduce)').matches
}

function animateIn(el: Element, done: () => void) {
  const target = el as HTMLElement
  if (prefersReducedMotion()) {
    target.style.opacity = '1'
    target.style.transform = 'translateY(0)'
    done()
    return
  }

  target.animate(
    [
      { opacity: '0', transform: 'translateY(12px)' },
      { opacity: '1', transform: 'translateY(0)' },
    ],
    { duration: 220, easing: 'ease-out', fill: 'forwards' },
  ).finished.finally(done)
}

function animateOut(el: Element, done: () => void) {
  const target = el as HTMLElement
  if (prefersReducedMotion()) {
    target.style.opacity = '0'
    target.style.transform = 'translateY(12px)'
    done()
    return
  }

  target.animate(
    [
      { opacity: '1', transform: 'translateY(0)' },
      { opacity: '0', transform: 'translateY(12px)' },
    ],
    { duration: 180, easing: 'ease-in', fill: 'forwards' },
  ).finished.finally(done)
}

const AGENT_TYPES = ['general', 'schedule_planner', 'executor', 'librarian', 'analyst']
const AVAILABLE_TOOLS = ['file_operations', 'web_search', 'code_execution', 'database', 'api_calls', 'shell', 'git', 'calendar', 'tasks']
const VISIBILITY_OPTIONS = ['private', 'team', 'market'] as const
const SOURCE_OPTIONS = ['all', 'builtin', 'custom'] as const
const STATUS_OPTIONS = ['all', 'active', 'inactive'] as const

const BUILTIN_MCP_PACKS = [
  {
    id: 'mcp-schedule-coordinator',
    name: '鏃ョ▼鍗忚皟宸ュ叿鍖?',
    agentType: 'schedule_planner',
    category: 'planning',
    tools: ['calendar', 'tasks'],
    description: '鍥寸粫鎺掓湡銆佸啿绐佽瘑鍒笌璁″垝钀藉湴缁勭粐鍙墽琛屽伐鍏疯兘鍔涖€?',
  },
  {
    id: 'mcp-execution-ops',
    name: '鎵ц鎺ㄨ繘宸ュ叿鍖?',
    agentType: 'executor',
    category: 'operations',
    tools: ['shell', 'api_calls', 'git'],
    description: '涓烘墽琛岃鑹叉彁渚涗换鍔℃帹杩涖€佸懡浠ゆ墽琛屼笌澶栭儴浜や簰鑳藉姏銆?',
  },
  {
    id: 'mcp-knowledge-pipeline',
    name: '鐭ヨ瘑娌夋穩宸ュ叿鍖?',
    agentType: 'librarian',
    category: 'knowledge',
    tools: ['web_search', 'database'],
    description: '鏀寔妫€绱€佹暣鐞嗕笌鍥捐氨娌夋穩绛夌煡璇嗗伐浣滄祦銆?',
  },
  {
    id: 'mcp-analysis-console',
    name: '鍒嗘瀽娲炲療宸ュ叿鍖?',
    agentType: 'analyst',
    category: 'analysis',
    tools: ['database', 'api_calls', 'code_execution'],
    description: '鑱氬悎鍒嗘瀽銆佸姣斾笌娲炲療鏁寸悊鎵€闇€鐨勬牳蹇冨伐鍏枫€?',
  },
] as const

type BuiltinMcpPack = (typeof BUILTIN_MCP_PACKS)[number]

export function useSkillsPage() {
  const skills = ref<Skill[]>([])
  const loading = ref(false)
  const saving = ref(false)
  const modalOpen = ref(false)
  const mcpPanelOpen = ref(false)
  const editingSkill = ref<Skill | null>(null)
  const selectedSkillId = ref<string | null>(null)
  const detailDrawerOpen = ref(false)
  const drawerTitleId = 'skills-detail-drawer-title'
  const drawerDescriptionId = 'skills-detail-drawer-description'
  const drawerPanelRef = ref<HTMLElement | null>(null)
  const lastTriggerElement = ref<HTMLElement | null>(null)
  const searchQuery = ref('')
  const selectedAgentFilter = ref<'all' | string>('all')
  const selectedSourceFilter = ref<(typeof SOURCE_OPTIONS)[number]>('all')
  const selectedStatusFilter = ref<(typeof STATUS_OPTIONS)[number]>('all')
  const selectedVisibilityFilter = ref<'all' | Skill['visibility']>('all')

  const mcpPacksByAgent = computed(() => {
    return BUILTIN_MCP_PACKS.reduce<Record<string, BuiltinMcpPack[]>>((acc, pack) => {
      const existing = acc[pack.agentType] || []
      acc[pack.agentType] = [...existing, pack]
      return acc
    }, {})
  })

  const activeSkillCount = computed(() => skills.value.filter(skill => skill.is_active).length)
  const coverageToolCount = computed(() => new Set(skills.value.flatMap(skill => skill.tools)).size)
  const activeRatio = computed(() => skills.value.length ? `${Math.round((activeSkillCount.value / skills.value.length) * 100)}%` : '0%')
  const selectedSkill = computed(() => skills.value.find(skill => skill.id === selectedSkillId.value) ?? null)

  const filteredSkills = computed(() => {
    const keyword = searchQuery.value.trim().toLowerCase()
    return skills.value.filter((skill) => {
      const matchesKeyword = !keyword || [
        skill.name,
        skill.description || '',
        skill.agent_type,
        skill.visibility,
        ...skill.tools,
      ].some(value => value.toLowerCase().includes(keyword))

      const matchesAgent = selectedAgentFilter.value === 'all' || skill.agent_type === selectedAgentFilter.value
      const matchesSource = selectedSourceFilter.value === 'all'
        || (selectedSourceFilter.value === 'builtin' ? skill.is_builtin : !skill.is_builtin)
      const matchesStatus = selectedStatusFilter.value === 'all'
        || (selectedStatusFilter.value === 'active' ? skill.is_active : !skill.is_active)
      const matchesVisibility = selectedVisibilityFilter.value === 'all' || skill.visibility === selectedVisibilityFilter.value

      return matchesKeyword && matchesAgent && matchesSource && matchesStatus && matchesVisibility
    })
  })

  const form = ref<SkillCreate>({
    name: '',
    description: '',
    instructions: '',
    agent_type: 'general',
    tools: [],
    visibility: 'private',
    is_active: true,
  })

  function resetForm() {
    form.value = {
      name: '',
      description: '',
      instructions: '',
      agent_type: 'general',
      tools: [],
      visibility: 'private',
      is_active: true,
    }
  }

  function openCreateModal() {
    editingSkill.value = null
    resetForm()
    modalOpen.value = true
  }

  function openEditModal(skill: Skill) {
    editingSkill.value = skill
    form.value = {
      name: skill.name,
      description: skill.description || '',
      instructions: skill.instructions,
      agent_type: skill.agent_type,
      tools: [...skill.tools],
      visibility: skill.visibility,
      is_active: skill.is_active,
    }
    modalOpen.value = true
  }

  function closeModal() {
    modalOpen.value = false
    editingSkill.value = null
    resetForm()
  }

  function openMcpPanel() {
    mcpPanelOpen.value = true
  }

  function closeMcpPanel() {
    mcpPanelOpen.value = false
  }

  function selectSkill(skillId: string, trigger?: EventTarget | null) {
    selectedSkillId.value = skillId
    lastTriggerElement.value = trigger instanceof HTMLElement ? trigger : null
    detailDrawerOpen.value = true
  }

  function closeDetailDrawer() {
    detailDrawerOpen.value = false
  }

  function handleDrawerKeydown(event: KeyboardEvent) {
    if (event.key === 'Escape') {
      event.preventDefault()
      closeDetailDrawer()
      return
    }

    if (event.key !== 'Tab' || !drawerPanelRef.value) return

    const focusableElements = Array.from(
      drawerPanelRef.value.querySelectorAll<HTMLElement>('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),
    ).filter(element => !element.hasAttribute('disabled'))

    if (focusableElements.length === 0) return

    const firstElement = focusableElements[0]
    const lastElement = focusableElements[focusableElements.length - 1]
    const activeElement = document.activeElement

    if (event.shiftKey && activeElement === firstElement) {
      event.preventDefault()
      lastElement.focus()
      return
    }

    if (!event.shiftKey && activeElement === lastElement) {
      event.preventDefault()
      firstElement.focus()
    }
  }

  function formatRelativeTime(value: string) {
    const timestamp = new Date(value).getTime()
    if (Number.isNaN(timestamp)) return '--'
    const diffMinutes = Math.max(0, Math.floor((Date.now() - timestamp) / 60000))
    if (diffMinutes < 1) return '鍒氬垰'
    if (diffMinutes < 60) return `${diffMinutes}m ago`
    const diffHours = Math.floor(diffMinutes / 60)
    if (diffHours < 24) return `${diffHours}h ago`
    const diffDays = Math.floor(diffHours / 24)
    return `${diffDays}d ago`
  }

  function getBindingCount(skill: Skill) {
    return Math.max(1, Math.min(4, skill.tools.length || 1))
  }

  function getSourceLabel(skill: Skill) {
    return skill.is_builtin ? 'BUILT-IN' : 'CUSTOM'
  }

  function getStatusLabel(skill: Skill) {
    return skill.is_active ? 'ACTIVE' : 'INACTIVE'
  }

  function getToolPreview(skill: Skill) {
    return skill.tools.slice(0, 3)
  }

  function getToolOverflow(skill: Skill) {
    return Math.max(0, skill.tools.length - 3)
  }

  async function fetchSkills() {
    loading.value = true
    try {
      const res = await skillApi.list()
      if (res.data.length === 0) {
        const bootstrapRes = await skillApi.bootstrapBuiltin()
        skills.value = bootstrapRes.data
      } else {
        skills.value = res.data
      }
      selectedSkillId.value = skills.value[0]?.id ?? null
      detailDrawerOpen.value = false
    } catch (e) {
      console.error('Failed to fetch skills', e)
    } finally {
      loading.value = false
    }
  }

  async function createSkill() {
    saving.value = true
    try {
      const res = await skillApi.create(form.value)
      skills.value = [...skills.value, res.data]
      selectedSkillId.value = res.data.id
      detailDrawerOpen.value = true
      closeModal()
    } catch (e) {
      console.error('Failed to create skill', e)
    } finally {
      saving.value = false
    }
  }

  async function updateSkill() {
    if (!editingSkill.value) return
    saving.value = true
    try {
      const res = await skillApi.update(editingSkill.value.id, form.value)
      skills.value = skills.value.map(skill => skill.id === editingSkill.value?.id ? res.data : skill)
      selectedSkillId.value = res.data.id
      detailDrawerOpen.value = true
      closeModal()
    } catch (e) {
      console.error('Failed to update skill', e)
    } finally {
      saving.value = false
    }
  }

  async function deleteSkill(skill: Skill) {
    if (!confirm(`Delete skill "${skill.name}"?`)) return
    try {
      await skillApi.delete(skill.id)
      skills.value = skills.value.filter(s => s.id !== skill.id)
      if (selectedSkillId.value === skill.id) {
        selectedSkillId.value = skills.value[0]?.id ?? null
        if (!selectedSkillId.value) {
          detailDrawerOpen.value = false
        }
      }
    } catch (e) {
      console.error('Failed to delete skill', e)
    }
  }

  async function toggleActive(skill: Skill) {
    try {
      const res = await skillApi.update(skill.id, { is_active: !skill.is_active })
      skills.value = skills.value.map(item => item.id === skill.id ? res.data : item)
    } catch (e) {
      console.error('Failed to toggle skill active state', e)
    }
  }

  function copySkill(skill: Skill) {
    const skillText = JSON.stringify({
      name: skill.name,
      description: skill.description,
      instructions: skill.instructions,
      agent_type: skill.agent_type,
      tools: skill.tools,
      visibility: skill.visibility,
    }, null, 2)
    navigator.clipboard.writeText(skillText).catch(e => {
      console.error('Failed to copy skill', e)
    })
  }

  function toggleTool(tool: string) {
    const idx = form.value.tools?.indexOf(tool) ?? -1
    if (idx === -1) {
      form.value.tools = [...(form.value.tools || []), tool]
    } else {
      form.value.tools = form.value.tools?.filter(t => t !== tool) ?? []
    }
  }

  watch(detailDrawerOpen, async (isOpen) => {
    if (isOpen) {
      await nextTick()
      drawerPanelRef.value?.focus()
      return
    }

    const target = lastTriggerElement.value
    lastTriggerElement.value = null
    target?.focus()
  })

  watch(skills, (nextSkills) => {
    if (selectedSkillId.value && !nextSkills.some(skill => skill.id === selectedSkillId.value)) {
      selectedSkillId.value = null
      detailDrawerOpen.value = false
    }
  })

  onMounted(fetchSkills)
  onBeforeUnmount(() => {
    lastTriggerElement.value = null
  })

  return {
    AGENT_TYPES,
    AVAILABLE_TOOLS,
    VISIBILITY_OPTIONS,
    SOURCE_OPTIONS,
    STATUS_OPTIONS,
    BUILTIN_MCP_PACKS,
    skills,
    loading,
    saving,
    modalOpen,
    mcpPanelOpen,
    editingSkill,
    detailDrawerOpen,
    drawerTitleId,
    drawerDescriptionId,
    drawerPanelRef,
    searchQuery,
    selectedAgentFilter,
    selectedSourceFilter,
    selectedStatusFilter,
    selectedVisibilityFilter,
    mcpPacksByAgent,
    activeSkillCount,
    coverageToolCount,
    activeRatio,
    selectedSkill,
    filteredSkills,
    form,
    openCreateModal,
    openEditModal,
    closeModal,
    openMcpPanel,
    closeMcpPanel,
    selectSkill,
    closeDetailDrawer,
    handleDrawerKeydown,
    formatRelativeTime,
    getBindingCount,
    getSourceLabel,
    getStatusLabel,
    getToolPreview,
    getToolOverflow,
    createSkill,
    updateSkill,
    deleteSkill,
    toggleActive,
    copySkill,
    toggleTool,
    animateIn,
    animateOut,
  }
}
