import { useMemo, useState } from 'react'
import { motion } from 'framer-motion'
import { FileOutput, FileText, Wrench, X } from 'lucide-react'
import {
  artifactMap,
  knowledgeAreas,
  processes,
  toolMap,
  normalizeProcessRef,
} from '@/data'
import type { Process, ProcessRef } from '@/types/itto'

type ViewKey = 'inputs' | 'tools' | 'outputs'

type CollectionItem = {
  label: string
  details: string[]
}

type CollectionRow = {
  processId: string
  processCode: string
  processName: string
  processNameEn: string
  items: CollectionItem[]
}

type CollectionArea = {
  id: string
  order: number
  name: string
  nameEn: string
  color: string
  rows: CollectionRow[]
}

const tabs: Array<{ key: ViewKey; label: string; icon: typeof FileText }> = [
  { key: 'inputs', label: '输入', icon: FileText },
  { key: 'tools', label: '工具', icon: Wrench },
  { key: 'outputs', label: '输出', icon: FileOutput },
]

const containerVariants = {
  hidden: { opacity: 0 },
  visible: { opacity: 1, transition: { staggerChildren: 0.03 } },
}

const itemVariants = {
  hidden: { opacity: 0, y: 10 },
  visible: { opacity: 1, y: 0 },
}

function formatRef(ref: ProcessRef, viewKey: ViewKey): CollectionItem {
  const normalized = normalizeProcessRef(ref)
  const entity = viewKey === 'tools' ? toolMap.get(normalized.id) : artifactMap.get(normalized.id)
  const label = entity?.name ?? normalized.id
  const details = normalized.detail?.map((item) => item.label).filter(Boolean) ?? []

  return { label, details }
}

function getRefsByView(process: Process, viewKey: ViewKey) {
  if (viewKey === 'inputs') return process.inputs
  if (viewKey === 'tools') return process.tools
  return process.outputs
}

function uniqueItems(items: CollectionItem[]) {
  const seen = new Set<string>()
  return items.filter((item) => {
    const key = `${item.label}__${item.details.join('、')}`
    if (seen.has(key)) return false
    seen.add(key)
    return true
  })
}

function itemMatchesSelected(item: CollectionItem, selectedText: string | null) {
  if (!selectedText) return false
  return item.label === selectedText || item.details.includes(selectedText)
}

function renderSelectableText(
  text: string,
  selectedText: string | null,
  onSelect: (text: string) => void
) {
  const isSelected = selectedText === text

  return (
    <button
      type="button"
      aria-pressed={isSelected}
      onClick={() => onSelect(text)}
      className={`mx-[-2px] rounded px-0.5 text-left transition-colors hover:bg-indigo-50 hover:text-indigo-600 dark:hover:bg-indigo-900/40 dark:hover:text-indigo-300 ${
        isSelected
          ? 'bg-yellow-200 text-yellow-950 ring-1 ring-yellow-300 dark:bg-yellow-500/30 dark:text-yellow-100 dark:ring-yellow-500/40'
          : 'text-gray-700 dark:text-gray-300'
      }`}
    >
      {text}
    </button>
  )
}

function renderCollectionItems(
  items: CollectionItem[],
  selectedText: string | null,
  onSelect: (text: string) => void
) {
  return items.map((item, itemIndex) => (
    <span key={`${item.label}-${item.details.join('-')}-${itemIndex}`}>
      {itemIndex > 0 && <span className="text-gray-400 dark:text-gray-500">；</span>}
      {renderSelectableText(item.label, selectedText, onSelect)}
      {item.details.length > 0 && (
        <span>
          <span className="text-gray-500 dark:text-gray-400">（</span>
          {item.details.map((detail, detailIndex) => (
            <span key={`${item.label}-${detail}-${detailIndex}`}>
              {detailIndex > 0 && <span className="text-gray-400 dark:text-gray-500">、</span>}
              {renderSelectableText(detail, selectedText, onSelect)}
            </span>
          ))}
          <span className="text-gray-500 dark:text-gray-400">）</span>
        </span>
      )}
    </span>
  ))
}

function buildCollection(viewKey: ViewKey): CollectionArea[] {
  return knowledgeAreas.map((area) => {
    const rows = processes
      .filter((process) => process.knowledgeAreaId === area.id)
      .sort((a, b) => a.order - b.order)
      .map((process) => ({
        processId: process.id,
        processCode: process.code,
        processName: process.name,
        processNameEn: process.nameEn,
        items: uniqueItems(getRefsByView(process, viewKey).map((ref) => formatRef(ref, viewKey))),
      }))

    return {
      id: area.id,
      order: area.order,
      name: area.name,
      nameEn: area.nameEn,
      color: area.color,
      rows,
    }
  })
}

export function IttoCollectionsPage() {
  const [activeTab, setActiveTab] = useState<ViewKey>('inputs')
  const [selectedText, setSelectedText] = useState<string | null>(null)
  const collection = useMemo(() => buildCollection(activeTab), [activeTab])
  const activeLabel = tabs.find((tab) => tab.key === activeTab)?.label

  return (
    <div className="space-y-4">
      <div className="space-y-3 sticky top-20 z-30 rounded-2xl bg-gray-50/95 pb-1 backdrop-blur dark:bg-gray-900/95">
        <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
          <div>
            <h1 className="text-xl font-bold text-gray-900 dark:text-white">输入 · 工具 · 输出</h1>
            <p className="text-sm text-gray-500 dark:text-gray-400">按知识领域与子过程汇总</p>
          </div>
          <div className="inline-flex rounded-xl bg-white p-1 shadow-sm ring-1 ring-gray-100 dark:bg-gray-800 dark:ring-gray-700">
            {tabs.map((tab) => {
              const Icon = tab.icon
              const isActive = activeTab === tab.key
              return (
                <button
                  key={tab.key}
                  type="button"
                  onClick={() => setActiveTab(tab.key)}
                  className={`inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors ${
                    isActive
                      ? 'bg-indigo-600 text-white shadow-sm'
                      : 'text-gray-600 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-gray-700'
                  }`}
                >
                  <Icon size={16} />
                  {tab.label}
                </button>
              )
            })}
          </div>
        </div>

        {selectedText && (
          <div className="flex flex-wrap items-center gap-2 rounded-xl bg-yellow-50 px-4 py-3 text-sm text-yellow-900 ring-1 ring-yellow-200 dark:bg-yellow-500/10 dark:text-yellow-100 dark:ring-yellow-500/30">
            <span className="font-medium">标签：{selectedText}</span>
            <button
              type="button"
              onClick={() => setSelectedText(null)}
              className="inline-flex h-6 w-6 items-center justify-center rounded-full text-yellow-700 transition-colors hover:bg-yellow-100 hover:text-yellow-900 dark:text-yellow-200 dark:hover:bg-yellow-500/20"
              aria-label="清除标签"
            >
              <X size={14} />
            </button>
          </div>
        )}
      </div>

      <motion.div
        key={activeTab}
        variants={containerVariants}
        initial="hidden"
        animate="visible"
        className="space-y-4"
      >
        {collection.map((area) => (
          <motion.section
            key={area.id}
            variants={itemVariants}
            className="overflow-hidden rounded-xl bg-white shadow-sm ring-1 ring-gray-100 dark:bg-gray-800 dark:ring-gray-700"
          >
            <div
              className="flex items-center gap-3 border-b border-gray-100 p-4 dark:border-gray-700"
              style={{ backgroundColor: `${area.color}10` }}
            >
              <div
                className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-sm font-bold text-white"
                style={{ backgroundColor: area.color }}
              >
                {area.order}
              </div>
              <div className="min-w-0">
                <h2 className="text-base font-semibold text-gray-900 dark:text-white">{area.name}</h2>
                <p className="truncate text-xs text-gray-500 dark:text-gray-400">{area.nameEn}</p>
              </div>
            </div>

            <div className="overflow-x-auto">
              <table className="min-w-full divide-y divide-gray-100 dark:divide-gray-700">
                <thead className="bg-gray-50 dark:bg-gray-900/40">
                  <tr>
                    <th className="w-52 px-4 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400">
                      子过程
                    </th>
                    <th className="px-4 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400">
                      {activeLabel}
                    </th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-gray-100 dark:divide-gray-700">
                  {area.rows.map((row) => {
                    const rowMatched = row.items.some((item) => itemMatchesSelected(item, selectedText))
                    return (
                      <tr
                        key={row.processId}
                        className={`align-top transition-colors ${
                          rowMatched ? 'bg-yellow-50/60 dark:bg-yellow-500/5' : ''
                        }`}
                      >
                        <td className="px-4 py-3">
                          <div className="flex items-start gap-2">
                            <span
                              className="mt-0.5 inline-flex shrink-0 rounded-md px-2 py-0.5 text-xs font-semibold text-white"
                              style={{ backgroundColor: area.color }}
                            >
                              {row.processCode}
                            </span>
                            <div className="min-w-0">
                              <div className="text-sm font-medium text-gray-900 dark:text-white">{row.processName}</div>
                              <div className="text-xs text-gray-500 dark:text-gray-400">{row.processNameEn}</div>
                            </div>
                          </div>
                        </td>
                        <td className="px-4 py-3 text-sm leading-6 text-gray-700 dark:text-gray-300">
                          {renderCollectionItems(row.items, selectedText, setSelectedText)}
                        </td>
                      </tr>
                    )
                  })}
                </tbody>
              </table>
            </div>
          </motion.section>
        ))}
      </motion.div>
    </div>
  )
}
