"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { AlertTriangle, CheckCircle2, Clipboard, 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 [, setTick] = useState(0); // 用于强制更新计时显示

  // 设置页面标题
  useEffect(() => {
    document.title = "任务管理 - 抖歪";
    return () => {
      document.title = "抖歪 - 记录当下时代";
    };
  }, []);

  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 newTasks: Task[] = [];
      for (const url of notDuplicated) {
        const id = `${now}-${Math.random().toString(36).slice(2, 8)}`;
        newTasks.push({ id, url, status: "pending" });
      }
      // 新任务添加到最前面
      return [...newTasks, ...prev];
    });
  }, [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 handlePasteAndAdd = useCallback(async () => {
    try {
      const text = await navigator.clipboard.readText();
      const urls = extractDouyinLinks(text);
      if (!urls.length) {
        alert("剪贴板中未检测到 Douyin 短链，请复制包含 https://v.douyin.com/... 的文本");
        return;
      }
      addTasks(urls);
    } catch (err) {
      alert("无法读取剪贴板内容，请检查浏览器权限设置");
      console.error("Clipboard read error:", err);
    }
  }, [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(), error: undefined } : t));
    try {
      const res = await fetch(`/api/fetcher?url=${encodeURIComponent(task.url)}`, { signal: ctrl.signal, method: "GET" });
      const data = await res.json().catch(() => null);
      
      if (!res.ok) {
        // 使用后端返回的结构化错误信息
        const errorMsg = data?.error || `请求失败: ${res.status}`;
        const errorCode = data?.code || 'UNKNOWN';
        throw new Error(`${errorMsg} (${errorCode})`);
      }
      
      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]);

  // 定时器更新运行中任务的耗时显示
  useEffect(() => {
    const hasRunningTasks = tasks.some(t => t.status === "running");
    if (!hasRunningTasks) return;

    const timer = setInterval(() => {
      setTick(prev => prev + 1);
    }, 1000); // 每秒更新一次

    return () => clearInterval(timer);
  }, [tasks]);

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

  const retryTask = useCallback((taskId: string) => {
    setTasks(prev => prev.map(t => {
      if (t.id === taskId) {
        return { ...t, status: "pending" as TaskStatus, error: undefined, result: undefined };
      }
      return t;
    }));
  }, []);

  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 = (startTime?: number, endTime?: number) => {
    if (!startTime) return "";
    const end = endTime || Date.now();
    const secs = Math.max(0, Math.round((end - startTime) / 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 flex-wrap 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={handlePasteAndAdd} className="inline-flex items-center gap-2 rounded-md bg-emerald-600/90 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-emerald-600 focus:outline-none focus:ring-2 focus:ring-emerald-400/40">
              <Clipboard 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">用时 {formatDuration(t.startedAt, t.finishedAt)}</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="flex shrink-0 items-center gap-2">
                      {t.status === 'success' && t.result?.data?.aweme_id && (
                        <a 
                          href={`/aweme/${t.result.data.aweme_id}`} 
                          target="_blank" 
                          rel="noreferrer"
                          className="inline-flex items-center gap-1 rounded-md bg-emerald-600/80 px-2 py-1 text-xs text-white transition-colors hover:bg-emerald-600"
                        >
                          <ExternalLink className="h-3.5 w-3.5"/> 查看作品
                        </a>
                      )}
                      {t.status === 'error' && (
                        <button 
                          onClick={() => retryTask(t.id)} 
                          className="inline-flex items-center gap-1 rounded-md bg-amber-600/80 px-2 py-1 text-xs text-white transition-colors hover:bg-amber-600"
                        >
                          <PlayCircle className="h-3.5 w-3.5"/> 重试
                        </button>
                      )}
                      {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' && t.error && (
                        <div className="mb-3 space-y-2">
                          <div className="flex items-start gap-2 rounded-md border border-red-500/30 bg-red-500/10 p-3">
                            <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-red-400"/>
                            <div className="min-w-0 flex-1">
                              <div className="text-sm font-medium text-red-200">爬取失败</div>
                              <div className="mt-1 text-xs text-red-300/90">{t.error}</div>
                            </div>
                          </div>
                          <div className="text-xs text-neutral-400">
                            <strong>常见原因:</strong>
                            <ul className="ml-4 mt-1 list-disc space-y-0.5">
                              <li>视频已被删除或设为私密</li>
                              <li>网络连接问题或请求超时</li>
                              <li>抖音接口限流或反爬虫</li>
                            </ul>
                          </div>
                        </div>
                      )}
                      {typeof t.result !== 'undefined' && (
                        <div>
                          {t.result?.data?.aweme && (
                            <div className="mb-3 space-y-2 rounded-md border border-emerald-500/20 bg-emerald-500/5 p-3 text-xs">
                              <div className="flex items-center gap-2">
                                <CheckCircle2 className="h-4 w-4 text-emerald-400"/>
                                <span className="font-medium text-emerald-200">作品信息</span>
                              </div>
                              <div className="space-y-1 text-neutral-300">
                                <div><span className="text-neutral-400">ID:</span> {t.result.data.aweme.aweme_id}</div>
                                <div><span className="text-neutral-400">描述:</span> {t.result.data.aweme.desc || '(无)'}</div>
                                {t.result.data.aweme.author && (
                                  <div><span className="text-neutral-400">作者:</span> {t.result.data.aweme.author.nickname}</div>
                                )}
                              </div>
                            </div>
                          )}
                          <details className="group">
                            <summary className="cursor-pointer text-xs text-neutral-400 hover:text-neutral-300">
                              查看完整响应数据 <span className="group-open:hidden">▶</span><span className="hidden group-open:inline">▼</span>
                            </summary>
                            <pre className="mt-2 max-h-64 overflow-auto rounded bg-neutral-950 p-2 text-xs text-neutral-300">{JSON.stringify(t.result, null, 2)}</pre>
                          </details>
                        </div>
                      )}
                      {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>
  );
}
