"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { AlertTriangle, CheckCircle2, Clock, ExternalLink, Link2, Loader2, PlayCircle, Plus, Square, Trash2, X } from "lucide-react";

type TaskStatus = "pending" | "running" | "success" | "error";

type Task = {
  id: string;
  url: string;
  status: TaskStatus;
  startedAt?: number;
  finishedAt?: number;
  error?: string;
  result?: any;
};

const extractDouyinLinks = (text: string): string[] => {
  if (!text) return [];
  const regex = /https?:\/\/v\.douyin\.com\/\S+/g; // 粗略匹配直到空白
  const matches = text.match(regex) ?? [];
  const trailing = /[)\]】>。，、！!？?\s]+$/; // 去掉常见中文/英文结尾符号
  const cleaned = matches
    .map((m) => m.replace(trailing, ""))
    .map((m) => m.endsWith("/") ? m : m); // 保持原样，通常短链以 / 结尾
  // 去重
  return Array.from(new Set(cleaned));
};

export default function TasksPage() {
  const [input, setInput] = useState("");
  const [tasks, setTasks] = useState<Task[]>([]);
  const controllers = useRef<Map<string, AbortController>>(new Map());
  const [openDetails, setOpenDetails] = useState<Set<string>>(new Set());

  const inProgressUrls = useMemo(
    () => new Set(tasks.filter(t => t.status === "pending" || t.status === "running").map(t => t.url)),
    [tasks]
  );

  const addTasks = useCallback((urls: string[]) => {
    if (!urls.length) return;
    const now = Date.now();
    setTasks((prev) => {
      const existing = new Set(prev.map((t) => t.id));
      const notDuplicated = urls.filter(u => !inProgressUrls.has(u));
      const next: Task[] = [...prev];
      for (const url of notDuplicated) {
        const id = `${now}-${Math.random().toString(36).slice(2, 8)}`;
        next.push({ id, url, status: "pending" });
      }
      return next;
    });
  }, [inProgressUrls]);

  const handleSubmit = useCallback((e?: React.FormEvent) => {
    e?.preventDefault();
    const urls = extractDouyinLinks(input);
    if (!urls.length) {
      alert("未检测到 Douyin 短链，请粘贴包含 https://v.douyin.com/... 的文本");
      return;
    }
    addTasks(urls);
    setInput("");
  }, [input, addTasks]);

  const startTask = useCallback(async (task: Task) => {
    // 若已存在控制器，避免重复启动
    if (controllers.current.has(task.id)) return;
    const ctrl = new AbortController();
    controllers.current.set(task.id, ctrl);
    setTasks(prev => prev.map(t => t.id === task.id ? { ...t, status: "running", startedAt: Date.now() } : t));
    try {
      const res = await fetch(`/fetcher?url=${encodeURIComponent(task.url)}`, { signal: ctrl.signal, method: "GET" });
      if (!res.ok) {
        const text = await res.text().catch(() => "");
        throw new Error(text || `请求失败: ${res.status}`);
      }
      const data = await res.json().catch(() => undefined);
      setTasks(prev => prev.map(t => t.id === task.id ? { ...t, status: "success", finishedAt: Date.now(), result: data } : t));
    } catch (err: any) {
      const msg = err?.name === 'AbortError' ? '已取消' : (err?.message || String(err));
      setTasks(prev => prev.map(t => t.id === task.id ? { ...t, status: "error", finishedAt: Date.now(), error: msg } : t));
    } finally {
      controllers.current.delete(task.id);
    }
  }, []);

  // 自动拉起 pending 任务（使用 effect 防止每次 render 重复触发）
  useEffect(() => {
    const pending = tasks.filter(t => t.status === "pending");
    pending.forEach((t) => startTask(t));
  }, [tasks, startTask]);

  const cancelTask = useCallback((id: string) => {
    const ctrl = controllers.current.get(id);
    if (ctrl) ctrl.abort();
    controllers.current.delete(id);
  }, []);

  const clearFinished = useCallback(() => {
    setTasks(prev => prev.filter(t => t.status === "pending" || t.status === "running"));
  }, []);

  const toggleOpen = useCallback((id: string) => {
    setOpenDetails(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    })
  }, []);

  const extractedCount = useMemo(() => extractDouyinLinks(input).length, [input]);

  const formatDuration = (t?: number) => {
    if (!t) return "";
    const secs = Math.max(0, Math.round((Date.now() - t) / 1000));
    if (secs < 60) return `${secs}s`;
    const m = Math.floor(secs / 60);
    const s = secs % 60;
    return `${m}m ${s}s`;
  };

  const StatusBadge = ({ status }: { status: TaskStatus }) => {
    const base = "inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium";
    if (status === 'running') return <span className={`${base} bg-indigo-500/15 text-indigo-300`}><Loader2 className="h-3.5 w-3.5 animate-spin"/> 进行中</span>;
    if (status === 'pending') return <span className={`${base} bg-yellow-500/15 text-yellow-300`}><Clock className="h-3.5 w-3.5"/> 待开始</span>;
    if (status === 'success') return <span className={`${base} bg-emerald-500/15 text-emerald-300`}><CheckCircle2 className="h-3.5 w-3.5"/> 完成</span>;
    return <span className={`${base} bg-red-500/15 text-red-300`}><AlertTriangle className="h-3.5 w-3.5"/> 失败</span>;
  };

  return (
    <div className="relative min-h-dvh overflow-hidden bg-neutral-950 text-neutral-100">
      {/* 背景渐变（明确置于内容层后面） */}
      <div className="pointer-events-none absolute inset-0 -z-10 opacity-40 [mask-image:radial-gradient(60%_60%_at_50%_0%,#000_30%,transparent_70%)]">
        <div className="absolute -top-1/2 left-1/2 h-[120vh] w-[120vh] -translate-x-1/2 rounded-full bg-[conic-gradient(at_50%_50%,#312e81_0deg,#0ea5e9_120deg,#10b981_240deg,#312e81_360deg)] blur-3xl" />
      </div>

      <div className="relative z-10 mx-auto max-w-4xl px-5 py-12">
        <div className="mb-8">
          <h1 className="text-3xl font-semibold tracking-tight text-white">
            抖音采集任务
          </h1>
          <p className="mt-2 text-sm text-neutral-400">粘贴任意文本，我会自动提取 Douyin 短链并提交到后端处理。</p>
        </div>

        {/* 输入卡片 */}
        <form onSubmit={handleSubmit} className="rounded-xl border border-white/10 bg-white/5 p-4 shadow-[0_0_0_1px_rgba(255,255,255,0.03)] backdrop-blur">
          <div className="flex items-start gap-3">
            <div className="mt-1 rounded-md bg-neutral-900/60 p-2 ring-1 ring-white/5">
              <Link2 className="h-5 w-5 text-neutral-400" />
            </div>
            <div className="min-w-0 flex-1">
              <textarea
                className="w-full min-h-28 resize-y rounded-md border border-neutral-800/60 bg-neutral-900/60 px-3 py-2 text-sm placeholder:text-neutral-500 focus:border-indigo-700/50 focus:outline-none focus:ring-2 focus:ring-indigo-700/30"
                placeholder="例如：2.51 05/08 f@b.AT EUy:/ 无意之中... https://v.douyin.com/dP22IOH8uAI/ 复制此链接..."
                value={input}
                onChange={(e) => setInput(e.target.value)}
              />
              <div className="mt-2 flex items-center justify-between text-xs text-neutral-500">
                <span>已提取 {extractedCount} 个短链</span>
                <span className="hidden sm:inline">快捷键：Ctrl / Cmd + Enter 提交</span>
              </div>
            </div>
          </div>
          <div className="mt-4 flex items-center gap-3">
            <button type="submit" className="inline-flex items-center gap-2 rounded-md bg-indigo-600/90 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-400/40">
              <Plus className="h-4 w-4" /> 添加任务
            </button>
            <button type="button" onClick={clearFinished} className="inline-flex items-center gap-2 rounded-md bg-neutral-800 px-3 py-2 text-sm text-neutral-200 transition-colors hover:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-white/10">
              <Trash2 className="h-4 w-4" /> 清除已完成
            </button>
          </div>
        </form>

        {/* 任务列表 */}
        <section className="mt-8">
          <div className="mb-3 flex items-center justify-between">
            <h2 className="text-lg font-medium">进行中的任务</h2>
            <span className="text-xs text-neutral-400">共 {tasks.length} 个</span>
          </div>

          <ul className="space-y-3">
            {tasks.map((t) => {
              const isOpen = openDetails.has(t.id);
              return (
                <li key={t.id} className="rounded-xl border border-white/10 bg-white/5 p-4 shadow-[0_0_0_1px_rgba(255,255,255,0.03)] backdrop-blur">
                  <div className="flex items-start justify-between gap-4">
                    <div className="min-w-0 flex-1">
                      <div className="flex items-center gap-2">
                        <StatusBadge status={t.status} />
                        {t.status === 'running' && (
                          <span className="text-xs text-neutral-400">已耗时 {formatDuration(t.startedAt)}</span>
                        )}
                        {t.status === 'success' && (
                          <span className="text-xs text-neutral-400">用时 {t.startedAt ? formatDuration(t.startedAt) : '--'}</span>
                        )}
                      </div>
                      <div className="mt-1 flex items-center gap-2 text-sm text-neutral-200">
                        <span className="truncate" title={t.url}>{t.url}</span>
                        <a className="shrink-0 text-neutral-400 hover:text-neutral-200" href={t.url} target="_blank" rel="noreferrer">
                          <ExternalLink className="h-4 w-4" />
                        </a>
                      </div>
                    </div>
                    <div className="shrink-0 space-x-2">
                      {t.status === 'running' && (
                        <button onClick={() => cancelTask(t.id)} className="inline-flex items-center gap-1 rounded-md bg-red-600/80 px-2 py-1 text-xs text-white transition-colors hover:bg-red-600">
                          <Square className="h-3.5 w-3.5"/> 取消
                        </button>
                      )}
                      <button onClick={() => toggleOpen(t.id)} className="inline-flex items-center gap-1 rounded-md bg-neutral-800 px-2 py-1 text-xs text-neutral-200 transition-colors hover:bg-neutral-700">
                        {isOpen ? <X className="h-3.5 w-3.5"/> : <PlayCircle className="h-3.5 w-3.5" />} {isOpen ? '收起' : '详情'}
                      </button>
                    </div>
                  </div>

                  {/* 进度条 */}
                  {t.status === 'running' && (
                    <div className="mt-3 h-1 w-full overflow-hidden rounded bg-neutral-800">
                      <div className="h-full w-1/3 animate-[progress_1.2s_ease_infinite] rounded bg-indigo-500/70" />
                    </div>
                  )}

                  {isOpen && (
                    <div className="mt-3 rounded-md border border-neutral-800/60 bg-neutral-900/60 p-3">
                      {t.status === 'error' && (
                        <div className="mb-2 inline-flex items-center gap-2 rounded border border-red-500/30 bg-red-500/10 px-2 py-1 text-xs text-red-200">
                          <AlertTriangle className="h-4 w-4"/> {t.error}
                        </div>
                      )}
                      {typeof t.result !== 'undefined' && (
                        <pre className="max-h-64 overflow-auto rounded bg-neutral-950 p-2 text-xs text-neutral-300">{JSON.stringify(t.result, null, 2)}</pre>
                      )}
                      {typeof t.result === 'undefined' && t.status !== 'error' && (
                        <div className="text-xs text-neutral-400">暂无输出</div>
                      )}
                    </div>
                  )}
                </li>
              );
            })}

            {tasks.length === 0 && (
              <li className="rounded-xl border border-dashed border-white/10 bg-white/[0.03] p-8 text-center text-sm text-neutral-400">
                暂无任务，粘贴包含 Douyin 短链的文本后点击“添加任务”。
              </li>
            )}
          </ul>
        </section>
      </div>

      {/* 进度条动画 keyframes */}
      <style>{`@keyframes progress{0%{transform:translateX(-100%)}50%{transform:translateX(10%)}100%{transform:translateX(120%)}}`}</style>
    </div>
  );
}
