import { useEffect, useMemo, useState } from 'react'
import { useNavigate, useSearch } from '@tanstack/react-router'
import {
  ChevronLeft,
  Download,
  FileUp,
  Package,
  RefreshCw,
  RotateCw,
  Search,
  Trash2,
} from 'lucide-react'
import { api, type Dependency } from '@/api'
import { useDeps, useMiseList } from '@/api/hooks'
import { Button, Card, Checkbox, Input, Modal, PageHeader, Textarea } from '@/components/ui'
import { cn } from '@/lib/utils'

const LANG_LABEL: Record<string, string> = {
  python: 'Python',
  node: 'Node.js',
  ruby: 'Ruby',
  go: 'Go',
  rust: 'Rust',
  bun: 'Bun',
  php: 'PHP',
  deno: 'Deno',
  system: 'System',
}

export default function Dependencies() {
  const navigate = useNavigate()
  const search = useSearch({ strict: false }) as { language?: string; version?: string }
  const queryLang = search?.language || ''
  const queryVersion = search?.version || ''

  const [activeTab, setActiveTab] = useState(queryLang || 'python')
  const [keyword, setKeyword] = useState('')
  const [selected, setSelected] = useState<string[]>([])
  const [installOpen, setInstallOpen] = useState(false)
  const [importOpen, setImportOpen] = useState(false)
  const [logOpen, setLogOpen] = useState(false)
  const [deleteTarget, setDeleteTarget] = useState<Dependency | null>(null)
  const [forceDelete, setForceDelete] = useState(false)
  const [logContent, setLogContent] = useState('')
  const [logName, setLogName] = useState('')
  const [pkgName, setPkgName] = useState('')
  const [pkgVersion, setPkgVersion] = useState('')
  const [pkgRemark, setPkgRemark] = useState('')
  const [manifest, setManifest] = useState('')
  const [importDb, setImportDb] = useState(true)
  const [busy, setBusy] = useState(false)
  const [message, setMessage] = useState('')

  const language = queryLang || activeTab
  const langVersion = queryVersion || undefined

  const { data: miseData } = useMiseList()
  const { data: depsData, isLoading, refetch, isFetching } = useDeps({
    language,
    lang_version: langVersion,
  })

  const miseList = Array.isArray(miseData) ? miseData : []
  const deps = Array.isArray(depsData) ? depsData : []
  const installedLangs = useMemo(
    () => [...new Set(miseList.map((l) => l.plugin))].sort(),
    [miseList],
  )

  useEffect(() => {
    if (queryLang) setActiveTab(queryLang)
  }, [queryLang])

  useEffect(() => {
    if (queryLang) return
    if (installedLangs.length && !installedLangs.includes(activeTab) && activeTab !== 'system') {
      setActiveTab(installedLangs[0]!)
    }
  }, [installedLangs, activeTab, queryLang])

  const filtered = useMemo(() => {
    const list = deps.filter((d) => !language || d.language === language)
    if (!keyword.trim()) return list
    const q = keyword.toLowerCase()
    return list.filter((d) => d.name.toLowerCase().includes(q) || (d.remark || '').toLowerCase().includes(q))
  }, [deps, language, keyword])

  const allSelected = filtered.length > 0 && filtered.every((d) => selected.includes(d.id))

  function toggleAll(checked: boolean) {
    setSelected(checked ? filtered.map((d) => d.id) : [])
  }

  function toggleOne(id: string, checked: boolean) {
    setSelected((prev) => (checked ? [...new Set([...prev, id])] : prev.filter((x) => x !== id)))
  }

  async function installPackage() {
    if (!pkgName.trim()) {
      setMessage('请输入包名')
      return
    }
    setBusy(true)
    setMessage('')
    try {
      await api.deps.install({
        name: pkgName.trim(),
        version: pkgVersion.trim() || undefined,
        remark: pkgRemark.trim() || undefined,
        language,
        lang_version: langVersion,
      })
      setInstallOpen(false)
      setPkgName('')
      setPkgVersion('')
      setPkgRemark('')
      setMessage('安装指令已发送')
      toast.success('安装指令已发送')
      refetch()
    } catch (e: any) {
      setMessage(e?.message || '安装失败')
      toast.error(e?.message || '安装失败')
    } finally {
      setBusy(false)
    }
  }

  async function uninstall() {
    if (!deleteTarget) return
    setBusy(true)
    try {
      await api.deps.uninstall(deleteTarget.id, forceDelete)
      setDeleteTarget(null)
      setForceDelete(false)
      const msg = forceDelete ? '记录已强制移除' : '卸载成功'
      setMessage(msg)
      toast.success(msg)
      refetch()
    } catch (e: any) {
      setMessage(e?.message || '卸载失败')
      toast.error(e?.message || '卸载失败')
    } finally {
      setBusy(false)
    }
  }

  async function reinstall(dep: Dependency) {
    setBusy(true)
    try {
      await api.deps.reinstall(dep.id)
      setMessage(`已发送重装指令: ${dep.name}`)
      toast.success(`已发送重装指令: ${dep.name}`)
      refetch()
    } catch (e: any) {
      setMessage(e?.message || '重装失败')
      toast.error(e?.message || '重装失败')
    } finally {
      setBusy(false)
    }
  }

  async function reinstallAll() {
    setBusy(true)
    try {
      await api.deps.reinstallAll(language, langVersion)
      setMessage('全部重装指令已发送')
      toast.success('全部重装指令已发送')
      refetch()
    } catch (e: any) {
      setMessage(e?.message || '全部重装失败')
      toast.error(e?.message || '全部重装失败')
    } finally {
      setBusy(false)
    }
  }

  async function batchInstall() {
    if (!selected.length) return
    setBusy(true)
    try {
      const items = deps
        .filter((d) => selected.includes(d.id))
        .map((d) => ({
          name: d.name,
          version: d.version || undefined,
          language: d.language,
          lang_version: d.lang_version || undefined,
        }))
      const res = await api.deps.getBatchInstallCmd({ items })
      setSelected([])
      if (res.command) {
        setLogName('批量安装命令')
        setLogContent(res.command)
        setLogOpen(true)
        setMessage('已生成批量安装命令，可复制到终端执行')
        toast.success('已生成批量安装命令')
      }
    } catch (e: any) {
      setMessage(e?.message || '生成批量命令失败')
      toast.error(e?.message || '生成批量命令失败')
    } finally {
      setBusy(false)
    }
  }

  async function importManifest() {
    if (!manifest.trim()) {
      setMessage('请输入清单内容')
      toast.warning('请输入清单内容')
      return
    }
    setBusy(true)
    try {
      const res = await api.deps.import({
        language,
        lang_version: langVersion,
        content: manifest.trim(),
        import_db: importDb,
      })
      setImportOpen(false)
      setManifest('')
      if (res.command) {
        setLogName('导入安装命令')
        setLogContent(res.command)
        setLogOpen(true)
      }
      setMessage('依赖清单解析完成')
      toast.success('依赖清单解析完成')
      refetch()
    } catch (e: any) {
      setMessage(e?.message || '导入失败')
      toast.error(e?.message || '导入失败')
    } finally {
      setBusy(false)
    }
  }

  const tabs = queryLang
    ? [{ value: queryLang, label: LANG_LABEL[queryLang] || queryLang }]
    : [
        ...installedLangs.map((l) => ({ value: l, label: LANG_LABEL[l] || l })),
        { value: 'system', label: 'System' },
      ]

  return (
    <div>
      <PageHeader
        title="依赖管理"
        description="管理工具运行环境的依赖包"
        actions={
          <>
            {queryLang ? (
              <Button variant="secondary" onClick={() => navigate({ to: '/languages' })}>
                <ChevronLeft size={14} />
                返回语言
              </Button>
            ) : null}
            <Button variant="secondary" onClick={() => refetch()} disabled={isFetching}>
              <RefreshCw size={14} className={isFetching ? 'animate-spin' : ''} />
              刷新
            </Button>
            <Button
              variant="secondary"
              onClick={() => setImportOpen(true)}
              disabled={language !== 'python' && language !== 'node'}
            >
              <FileUp size={14} />
              导入清单
            </Button>
            <Button onClick={() => setInstallOpen(true)}>
              <Download size={14} />
              安装包
            </Button>
          </>
        }
      />

      {message ? (
        <div className="mb-3 rounded-md border border-[var(--border)] bg-[var(--bg-tertiary)] px-3 py-2 text-sm text-[var(--text-secondary)]">
          {message}
        </div>
      ) : null}

      {queryLang && queryVersion ? (
        <Card className="mb-4 flex items-center justify-between gap-3 p-3">
          <div className="flex items-center gap-2 text-sm">
            <Package size={16} className="text-[var(--text-muted)]" />
            正在管理环境:
            <span className="font-mono font-medium">
              {queryLang}@{queryVersion}
            </span>
          </div>
          <span className="rounded bg-[var(--bg-tertiary)] px-2 py-0.5 text-xs text-[var(--text-muted)]">隔离环境</span>
        </Card>
      ) : null}

      {!queryLang ? (
        <div className="mb-4 flex flex-wrap gap-2">
          {tabs.map((t) => (
            <Button
              key={t.value}
              size="sm"
              variant={activeTab === t.value ? 'default' : 'secondary'}
              onClick={() => {
                setActiveTab(t.value)
                setSelected([])
              }}
            >
              {t.label}
            </Button>
          ))}
        </div>
      ) : null}

      <Card className="overflow-hidden">
        <div className="flex flex-wrap items-center justify-between gap-3 border-b border-[var(--border)] px-4 py-3">
          <div className="flex flex-wrap items-center gap-2">
            <span className="rounded bg-[var(--bg-tertiary)] px-2 py-1 text-xs text-[var(--text-muted)]">
              {filtered.length} 个包
            </span>
            <div className="relative min-w-[180px]">
              <Search size={14} className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[var(--text-muted)]" />
              <Input className="pl-9" placeholder="搜索包名" value={keyword} onChange={(e) => setKeyword(e.target.value)} />
            </div>
          </div>
          <div className="flex flex-wrap gap-2">
            <Button size="sm" variant="secondary" disabled={!selected.length || busy} onClick={batchInstall}>
              批量安装命令
            </Button>
            <Button size="sm" variant="secondary" disabled={!filtered.length || busy} onClick={reinstallAll}>
              <RotateCw size={14} />
              全部重装
            </Button>
          </div>
        </div>

        <div className="flex items-center gap-3 border-b border-[var(--border)] bg-[var(--bg-tertiary)]/40 px-4 py-2 text-xs font-medium uppercase tracking-wide text-[var(--text-muted)]">
          <Checkbox checked={allSelected} onCheckedChange={(v) => toggleAll(v)} />
          <span className="hidden w-12 sm:block">序号</span>
          <span className="flex-1">包名</span>
          <span className="w-24">版本</span>
          <span className="hidden w-40 md:block">备注</span>
          <span className="w-36 text-right">操作</span>
        </div>

        {isLoading ? (
          <div className="p-6 text-sm text-[var(--text-muted)]">加载中...</div>
        ) : filtered.length === 0 ? (
          <div className="p-8 text-center text-sm text-[var(--text-muted)]">
            <Package className="mx-auto mb-2 opacity-50" size={28} />
            {keyword ? '无匹配结果' : '暂无依赖包'}
          </div>
        ) : (
          <div className="divide-y divide-[var(--border)]">
            {filtered.map((dep, index) => (
              <div
                key={dep.id}
                className={cn(
                  'flex items-center gap-3 px-4 py-2.5 text-sm',
                  selected.includes(dep.id) && 'bg-[var(--bg-tertiary)]/50',
                )}
              >
                <Checkbox
                  checked={selected.includes(dep.id)}
                  onCheckedChange={(v) => toggleOne(dep.id, v)}
                />
                <span className="hidden w-12 font-mono text-xs text-[var(--text-muted)] sm:block">{index + 1}</span>
                <div className="min-w-0 flex-1">
                  <div className="truncate font-medium">{dep.name}</div>
                  <div className="truncate text-xs text-[var(--text-muted)] md:hidden">{dep.remark || '-'}</div>
                </div>
                <span className="w-24 truncate font-mono text-xs text-[var(--text-muted)]">{dep.version || '-'}</span>
                <span className="hidden w-40 truncate text-xs text-[var(--text-muted)] md:block">{dep.remark || '-'}</span>
                <div className="flex w-36 justify-end gap-1">
                  <Button
                    size="sm"
                    variant="ghost"
                    onClick={() => {
                      setLogName(dep.name)
                      setLogContent(dep.log || '暂无日志')
                      setLogOpen(true)
                    }}
                  >
                    日志
                  </Button>
                  <Button size="sm" variant="ghost" disabled={busy} onClick={() => reinstall(dep)}>
                    重装
                  </Button>
                  <Button
                    size="sm"
                    variant="danger"
                    onClick={() => {
                      setDeleteTarget(dep)
                      setForceDelete(false)
                    }}
                  >
                    <Trash2 size={14} />
                  </Button>
                </div>
              </div>
            ))}
          </div>
        )}
      </Card>

      <Modal
        open={installOpen}
        title="安装依赖包"
        onClose={() => setInstallOpen(false)}
        footer={
          <>
            <Button variant="secondary" onClick={() => setInstallOpen(false)}>
              取消
            </Button>
            <Button onClick={installPackage} disabled={busy}>
              {busy ? '提交中...' : '安装'}
            </Button>
          </>
        }
      >
        <div className="space-y-3">
          <Input placeholder="包名 *" value={pkgName} onChange={(e) => setPkgName(e.target.value)} />
          <Input placeholder="版本（可选）" value={pkgVersion} onChange={(e) => setPkgVersion(e.target.value)} />
          <Input placeholder="备注（可选）" value={pkgRemark} onChange={(e) => setPkgRemark(e.target.value)} />
          <div className="text-xs text-[var(--text-muted)]">
            目标环境: {language}
            {langVersion ? `@${langVersion}` : ''}
          </div>
        </div>
      </Modal>

      <Modal
        open={importOpen}
        title="导入依赖清单"
        onClose={() => setImportOpen(false)}
        size="lg"
        footer={
          <>
            <Button variant="secondary" onClick={() => setImportOpen(false)}>
              取消
            </Button>
            <Button onClick={importManifest} disabled={busy}>
              {busy ? '解析中...' : '导入'}
            </Button>
          </>
        }
      >
        <div className="space-y-3">
          <Textarea
            className="min-h-[200px] font-mono text-xs"
            placeholder={language === 'python' ? 'requirements.txt 内容' : 'package.json dependencies 或 package list'}
            value={manifest}
            onChange={(e) => setManifest(e.target.value)}
          />
          <label className="flex items-center gap-2 text-sm">
            <Checkbox checked={importDb} onCheckedChange={setImportDb} />
            同时写入依赖数据库
          </label>
        </div>
      </Modal>

      <Modal
        open={!!deleteTarget}
        title="卸载依赖"
        onClose={() => setDeleteTarget(null)}
        footer={
          <>
            <Button variant="secondary" onClick={() => setDeleteTarget(null)}>
              取消
            </Button>
            <Button variant="danger" onClick={uninstall} disabled={busy}>
              确认卸载
            </Button>
          </>
        }
      >
        <div className="space-y-3 text-sm">
          <p>
            确认卸载 <strong>{deleteTarget?.name}</strong>？
          </p>
          <label className="flex items-center gap-2">
            <Checkbox checked={forceDelete} onCheckedChange={setForceDelete} />
            强制删除记录（跳过实际卸载）
          </label>
        </div>
      </Modal>

      <Modal open={logOpen} title={logName || '日志'} onClose={() => setLogOpen(false)} size="lg">
        <pre className="max-h-[60vh] overflow-auto whitespace-pre-wrap rounded-md bg-[var(--bg-primary)] p-3 font-mono text-xs text-[var(--text-secondary)]">
          {logContent || '(无内容)'}
        </pre>
      </Modal>
    </div>
  )
}
