import { useEffect, useMemo, useState } from 'react'
import { useNavigate } from '@tanstack/react-router'
import {
  Boxes,
  CheckCircle2,
  Info,
  Package,
  Plus,
  RefreshCw,
  Terminal as TerminalIcon,
  Trash2,
  Zap,
} from 'lucide-react'
import { api, type MiseLanguage } from '@/api'
import { useMiseList } from '@/api/hooks'
import { Button, Card, Input, Modal, PageHeader, Select, Tabs } from '@/components/ui'
import { toast } from '@/lib/toast'
import { cn } from '@/lib/utils'

type DisplayLang = MiseLanguage & { sourceText: string }

function sourceText(source: MiseLanguage['source']) {
  if (!source) return '-'
  if (typeof source === 'string') return source
  return source.path || source.type || '-'
}

export default function Languages() {
  const navigate = useNavigate()
  const [tab, setTab] = useState<'runtimes' | 'envs'>('runtimes')
  const [installOpen, setInstallOpen] = useState(false)
  const [plugins, setPlugins] = useState<string[]>([])
  const [versions, setVersions] = useState<string[]>([])
  const [plugin, setPlugin] = useState('python')
  const [version, setVersion] = useState('')
  const [cmdOpen, setCmdOpen] = useState(false)
  const [command, setCommand] = useState('')
  const [envs, setEnvs] = useState<Record<string, string>>({})
  const [envKey, setEnvKey] = useState('')
  const [envValue, setEnvValue] = useState('')
  const [busy, setBusy] = useState(false)
  const [message, setMessage] = useState('')
  const [showTip, setShowTip] = useState(() => localStorage.getItem('taskpool_show_mise_extension_tip') !== '0')

  const { data, isLoading, refetch, isFetching } = useMiseList()
  const list: DisplayLang[] = useMemo(
    () =>
      (Array.isArray(data) ? data : []).map((item) => ({
        ...item,
        sourceText: sourceText(item.source),
      })),
    [data],
  )

  useEffect(() => {
    if (tab !== 'envs') return
    api.mise
      .getEnvs()
      .then((res) => setEnvs(res || {}))
      .catch(() => setEnvs({}))
  }, [tab])

  useEffect(() => {
    if (!installOpen) return
    api.mise
      .plugins()
      .then((res) => {
        const arr = Array.isArray(res) ? res : []
        setPlugins(arr)
        if (arr.length && !arr.includes(plugin)) setPlugin(arr[0]!)
      })
      .catch(() => setPlugins(['python', 'node', 'go', 'php', 'ruby']))
  }, [installOpen])

  useEffect(() => {
    if (!installOpen || !plugin) return
    setVersions([])
    setVersion('')
    api.mise
      .versions(plugin)
      .then((res) => {
        const arr = Array.isArray(res) ? res : []
        setVersions(arr)
        if (arr[0]) setVersion(arr[0])
      })
      .catch(() => setVersions([]))
  }, [installOpen, plugin])

  async function sync() {
    setBusy(true)
    try {
      await api.mise.sync()
      setMessage('本地环境同步成功')
      toast.success('本地环境同步成功')
      refetch()
    } catch (e: any) {
      setMessage(e?.message || '同步失败')
      toast.error(e?.message || '同步失败')
    } finally {
      setBusy(false)
    }
  }

  function openInstallCmd() {
    if (!plugin || !version) return
    setCommand(`mise install ${plugin}@${version}`)
    setInstallOpen(false)
    setCmdOpen(true)
  }

  function uninstallCmd(lang: DisplayLang) {
    setCommand(`mise uninstall ${lang.plugin}@${lang.version}`)
    setCmdOpen(true)
  }

  async function verify(lang: DisplayLang) {
    try {
      const res = await api.mise.verifyCommand(lang.plugin, lang.version)
      setCommand(res.command)
      setCmdOpen(true)
    } catch (e: any) {
      setMessage(e?.message || '获取验证命令失败')
    }
  }

  async function toggleDefault(lang: DisplayLang) {
    setBusy(true)
    try {
      if (lang.is_global) {
        await api.mise.unsetGlobal(lang.plugin, lang.version)
        setMessage(`已取消 ${lang.plugin} 的全局默认`)
      } else {
        await api.mise.useGlobal(lang.plugin, lang.version)
        setMessage(`已将 ${lang.plugin} ${lang.version} 设为全局默认`)
      }
      refetch()
    } catch (e: any) {
      setMessage(e?.message || '操作失败')
    } finally {
      setBusy(false)
    }
  }

  async function saveEnv() {
    if (!envKey.trim()) return
    setBusy(true)
    try {
      await api.mise.setEnv(envKey.trim(), envValue)
      setEnvKey('')
      setEnvValue('')
      const res = await api.mise.getEnvs()
      setEnvs(res || {})
      setMessage('环境变量已保存')
    } catch (e: any) {
      setMessage(e?.message || '保存失败')
    } finally {
      setBusy(false)
    }
  }

  async function removeEnv(key: string) {
    setBusy(true)
    try {
      await api.mise.unsetEnv(key)
      const res = await api.mise.getEnvs()
      setEnvs(res || {})
    } catch (e: any) {
      setMessage(e?.message || '删除失败')
    } finally {
      setBusy(false)
    }
  }

  function closeTip() {
    setShowTip(false)
    localStorage.setItem('taskpool_show_mise_extension_tip', '0')
  }

  return (
    <div>
      <PageHeader
        title="语言依赖"
        description="管理编程语言及相关包依赖 (Mise)"
        actions={
          <>
            <Button variant="secondary" onClick={() => refetch()} disabled={isFetching}>
              <RefreshCw size={14} className={isFetching ? 'animate-spin' : ''} />
              刷新
            </Button>
            <Button variant="secondary" onClick={sync} disabled={busy}>
              同步
            </Button>
            <Button onClick={() => setInstallOpen(true)}>
              <Plus size={14} />
              新增语言
            </Button>
          </>
        }
      />

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

      <div className="mb-4 space-y-2">
        <div className="flex items-start gap-2 rounded-lg border border-amber-500/20 bg-amber-500/10 px-3 py-2 text-sm text-amber-600 dark:text-amber-400">
          <Info size={16} className="mt-0.5 shrink-0" />
          <span>
            <b>设为默认</b>：将选定版本设为系统全局默认，未指定环境的任务将调用此版本。
          </span>
        </div>
        {showTip ? (
          <div className="flex items-start justify-between gap-2 rounded-lg border border-blue-500/20 bg-blue-500/10 px-3 py-2 text-sm text-blue-600 dark:text-blue-400">
            <div className="flex items-start gap-2">
              <Info size={16} className="mt-0.5 shrink-0" />
              <span>Mise 也可管理其它工具插件，可在终端安装后通过同步展示。</span>
            </div>
            <button className="text-xs opacity-70 hover:opacity-100" onClick={closeTip}>
              关闭
            </button>
          </div>
        ) : null}
      </div>

      <div className="mb-4">
        <Tabs
          value={tab}
          onValueChange={(v) => setTab(v as 'runtimes' | 'envs')}
          items={[
            { value: 'runtimes', label: '运行时' },
            { value: 'envs', label: '加速/环境' },
          ]}
        />
      </div>

      {tab === 'runtimes' ? (
        <Card className="overflow-hidden">
          {isLoading ? (
            <div className="p-6 text-[var(--text-muted)]">加载中...</div>
          ) : list.length === 0 ? (
            <div className="p-8 text-center text-sm text-[var(--text-muted)]">
              <Boxes className="mx-auto mb-2 opacity-50" size={28} />
              暂无语言运行时，点击「新增语言」安装
            </div>
          ) : (
            <div className="divide-y divide-[var(--border)]">
              {list.map((lang, idx) => (
                <div
                  key={`${lang.plugin}-${lang.version}-${idx}`}
                  className="flex flex-col gap-3 p-4 md:flex-row md:items-center md:justify-between"
                >
                  <div className="min-w-0">
                    <div className="flex flex-wrap items-center gap-2">
                      <span className="font-medium">
                        {lang.plugin} {lang.version}
                      </span>
                      {lang.is_global ? (
                        <span className="inline-flex items-center gap-1 rounded bg-green-500/15 px-1.5 py-0.5 text-xs text-green-500">
                          <CheckCircle2 size={12} />
                          默认
                        </span>
                      ) : null}
                    </div>
                    <div className="mt-1 text-xs text-[var(--text-muted)]">
                      来源: {lang.sourceText} · {lang.install_path || '-'}
                    </div>
                  </div>
                  <div className="flex flex-wrap gap-2">
                    <Button
                      size="sm"
                      variant="secondary"
                      onClick={() =>
                        navigate({
                          to: '/dependencies',
                          search: { language: lang.plugin, version: lang.version },
                        })
                      }
                    >
                      <Package size={14} />
                      依赖
                    </Button>
                    <Button size="sm" variant="secondary" onClick={() => toggleDefault(lang)} disabled={busy}>
                      {lang.is_global ? '取消默认' : '设为默认'}
                    </Button>
                    <Button size="sm" variant="secondary" onClick={() => verify(lang)}>
                      <TerminalIcon size={14} />
                      验证
                    </Button>
                    <Button size="sm" variant="danger" onClick={() => uninstallCmd(lang)}>
                      <Trash2 size={14} />
                    </Button>
                  </div>
                </div>
              ))}
            </div>
          )}
        </Card>
      ) : (
        <div className="space-y-4">
          <Card className="space-y-3 p-4">
            <div className="flex items-center gap-2 text-sm font-medium">
              <Zap size={16} />
              Mise 环境变量（镜像加速等）
            </div>
            <div className="grid gap-3 md:grid-cols-[1fr_1fr_auto]">
              <Input placeholder="KEY" value={envKey} onChange={(e) => setEnvKey(e.target.value)} />
              <Input placeholder="VALUE" value={envValue} onChange={(e) => setEnvValue(e.target.value)} />
              <Button onClick={saveEnv} disabled={busy || !envKey.trim()}>
                保存
              </Button>
            </div>
          </Card>
          <Card className="overflow-hidden">
            {Object.keys(envs).length === 0 ? (
              <div className="p-6 text-sm text-[var(--text-muted)]">暂无环境变量</div>
            ) : (
              <div className="divide-y divide-[var(--border)]">
                {Object.entries(envs).map(([k, v]) => (
                  <div key={k} className="flex items-center justify-between gap-3 p-4 text-sm">
                    <div className="min-w-0">
                      <div className="font-mono font-medium">{k}</div>
                      <div className="truncate text-xs text-[var(--text-muted)]">{v}</div>
                    </div>
                    <Button size="sm" variant="danger" onClick={() => removeEnv(k)} disabled={busy}>
                      <Trash2 size={14} />
                    </Button>
                  </div>
                ))}
              </div>
            )}
          </Card>
        </div>
      )}

      <Modal
        open={installOpen}
        title="安装语言运行时"
        onClose={() => setInstallOpen(false)}
        footer={
          <>
            <Button variant="secondary" onClick={() => setInstallOpen(false)}>
              取消
            </Button>
            <Button onClick={openInstallCmd} disabled={!plugin || !version}>
              生成安装命令
            </Button>
          </>
        }
      >
        <div className="space-y-3">
          <Select value={plugin} onChange={(e) => setPlugin(e.target.value)}>
            {(plugins.length ? plugins : ['python', 'node', 'go', 'php', 'ruby']).map((p) => (
              <option key={p} value={p}>
                {p}
              </option>
            ))}
          </Select>
          <Select value={version} onChange={(e) => setVersion(e.target.value)}>
            {versions.length === 0 ? <option value="">加载版本中...</option> : null}
            {versions.map((v) => (
              <option key={v} value={v}>
                {v}
              </option>
            ))}
          </Select>
        </div>
      </Modal>

      <Modal
        open={cmdOpen}
        title="终端命令"
        onClose={() => setCmdOpen(false)}
        size="lg"
        footer={
          <>
            <Button
              variant="secondary"
              onClick={async () => {
                try {
                  await navigator.clipboard.writeText(command)
                  setMessage('命令已复制')
                } catch {
                  setMessage('复制失败')
                }
              }}
            >
              复制
            </Button>
            <Button
              onClick={async () => {
                setCmdOpen(false)
                await sync()
              }}
            >
              关闭并同步
            </Button>
          </>
        }
      >
        <pre className={cn('overflow-auto rounded-md bg-[var(--bg-primary)] p-3 font-mono text-xs')}>{command}</pre>
        <p className="mt-2 text-xs text-[var(--text-muted)]">请在「终端命令」页面或系统终端执行上述命令。</p>
      </Modal>
    </div>
  )
}
