"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { toast } from "sonner";
import { Play, GitCompareArrows, Pencil } from "lucide-react";
import {
  api,
  ApiError,
  type Connection,
  type Pipeline,
  type RunWithPipeline,
  type StreamConfig,
} from "@/components/api";
import { LogViewer } from "@/components/log-viewer";
import { StatusBadge } from "@/components/status-badge";
import { fmtTime, fmtDuration } from "@/components/format";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Textarea } from "@/components/ui/textarea";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";

export default function PipelineDetailPage() {
  const params = useParams<{ id: string }>();
  const id = Number(params.id);

  const [pipeline, setPipeline] = useState<Pipeline | null>(null);
  const [connMap, setConnMap] = useState<Record<number, string>>({});
  const [runs, setRuns] = useState<RunWithPipeline[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [runLoading, setRunLoading] = useState(false);
  const [diffLoading, setDiffLoading] = useState(false);
  const [diffSql, setDiffSql] = useState<string | null>(null);

  const loadRuns = useCallback(() => {
    api<RunWithPipeline[]>("/api/runs")
      .then((all) =>
        setRuns(all.filter((r) => r.pipeline_id === id))
      )
      .catch(() => {});
  }, [id]);

  useEffect(() => {
    Promise.all([
      api<Pipeline>(`/api/pipelines/${id}`),
      api<Connection[]>("/api/connections"),
    ])
      .then(([p, conns]) => {
        setPipeline(p);
        setConnMap(Object.fromEntries(conns.map((c) => [c.id, c.name])));
      })
      .catch((e) => setError(e instanceof Error ? e.message : "加载失败"))
      .finally(() => setLoading(false));
    loadRuns();
  }, [id, loadRuns]);

  // 有运行中的任务时轮询刷新历史列表
  const hasActive = runs.some(
    (r) => r.status === "running" || r.status === "queued"
  );
  useEffect(() => {
    if (!hasActive) return;
    const t = setInterval(loadRuns, 4000);
    return () => clearInterval(t);
  }, [hasActive, loadRuns]);

  const streams = useMemo<StreamConfig[]>(() => {
    if (!pipeline) return [];
    try {
      const v = JSON.parse(pipeline.streams);
      return Array.isArray(v) ? v : [];
    } catch {
      return [];
    }
  }, [pipeline]);

  const envEntries = useMemo<[string, string][]>(() => {
    if (!pipeline) return [];
    try {
      const v = JSON.parse(pipeline.env || "{}") as unknown;
      if (v && typeof v === "object" && !Array.isArray(v)) {
        return Object.entries(v as Record<string, unknown>).map(([k, val]) => [
          k,
          String(val),
        ]);
      }
    } catch {
      // fall through
    }
    return [];
  }, [pipeline]);

  const latestRun = runs[0] ?? null;

  async function runNow() {
    setRunLoading(true);
    try {
      await api(`/api/pipelines/${id}/run`, { method: "POST" });
      toast.success("已开始运行");
      loadRuns();
    } catch (e) {
      if (e instanceof ApiError && e.status === 409) {
        toast.info("该流水线正在运行中，请等待当前运行结束");
      } else {
        toast.error(e instanceof Error ? e.message : "启动失败");
      }
    } finally {
      setRunLoading(false);
    }
  }

  async function previewDiff() {
    setDiffLoading(true);
    setDiffSql(null);
    try {
      const res = await api<{ ok: boolean; sql: string }>(
        `/api/pipelines/${id}/diff`
      );
      setDiffSql(res.sql || "-- 无差异，schema 已一致");
      if (!res.ok) toast.info("Atlas 返回了非零状态，请检查 SQL 内容");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "获取 diff 失败");
    } finally {
      setDiffLoading(false);
    }
  }

  if (loading) return <div className="text-sm text-muted-foreground">加载中…</div>;
  if (error || !pipeline)
    return (
      <div className="text-sm text-red-500">
        {error ? `加载失败：${error}` : "流水线不存在"}
      </div>
    );

  const connName = (cid: number) => connMap[cid] ?? `#${cid}`;

  return (
    <div className="flex flex-col gap-6">
      <div className="flex items-center justify-between">
        <h1 className="text-xl font-semibold">{pipeline.name}</h1>
        <div className="flex gap-2">
          <Button variant="outline">
            <Link href={`/pipelines/${id}/edit`} className="flex items-center gap-1">
              <Pencil className="size-4" />
              编辑
            </Link>
          </Button>
          <Button variant="outline" onClick={previewDiff} disabled={diffLoading}>
            <GitCompareArrows className="size-4" />
            {diffLoading ? "Diff 计算中…" : "Schema Diff 预览"}
          </Button>
          <Button onClick={runNow} disabled={runLoading}>
            <Play className="size-4" />
            {runLoading ? "启动中…" : "运行"}
          </Button>
        </div>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>配置</CardTitle>
        </CardHeader>
        <CardContent>
          <dl className="grid grid-cols-2 gap-x-8 gap-y-2 text-sm sm:grid-cols-3">
            <div>
              <dt className="text-muted-foreground">源 → 目标</dt>
              <dd className="font-medium">
                {connName(pipeline.source_conn_id)} →{" "}
                {connName(pipeline.target_conn_id)}
              </dd>
            </div>
            <div>
              <dt className="text-muted-foreground">同步模式</dt>
              <dd className="font-mono">{pipeline.mode}</dd>
            </div>
            <div>
              <dt className="text-muted-foreground">表数量</dt>
              <dd>{streams.length}</dd>
            </div>
            <div>
              <dt className="text-muted-foreground">Schema 同步</dt>
              <dd>
                {pipeline.schema_sync ? (
                  <Badge variant="outline" className="border-green-500/40 bg-green-500/10 text-green-600 dark:text-green-400">
                    开
                  </Badge>
                ) : (
                  <Badge variant="outline" className="text-muted-foreground">
                    关
                  </Badge>
                )}
              </dd>
            </div>
            <div>
              <dt className="text-muted-foreground">同步范围</dt>
              <dd className="font-medium">
                {pipeline.schema_scope === "all" ? "整个库" : "仅选中的表"}
              </dd>
            </div>
            <div>
              <dt className="text-muted-foreground">包含外键</dt>
              <dd className="font-medium">{pipeline.include_fk ? "是" : "否"}</dd>
            </div>
            {envEntries.length > 0 ? (
              <div>
                <dt className="text-muted-foreground">环境变量</dt>
                <dd className="font-mono text-xs">
                  {envEntries.map(([k, v]) => `${k}=${v}`).join(" ")}
                </dd>
              </div>
            ) : null}
            <div>
              <dt className="text-muted-foreground">创建时间</dt>
              <dd>{fmtTime(pipeline.created_at)}</dd>
            </div>
            <div>
              <dt className="text-muted-foreground">更新时间</dt>
              <dd>{fmtTime(pipeline.updated_at)}</dd>
            </div>
          </dl>
          {streams.length > 0 ? (
            <div className="mt-3 flex flex-wrap gap-1">
              {streams.map((s) => (
                <Badge key={s.name} variant="secondary" className="font-mono">
                  {s.name}
                </Badge>
              ))}
            </div>
          ) : null}
        </CardContent>
      </Card>

      {diffLoading || diffSql !== null ? (
        <Card>
          <CardHeader>
            <CardTitle>Schema Diff（Atlas dry-run）</CardTitle>
            <CardDescription>
              目标库需要执行的 DDL。计算可能需要数十秒。
            </CardDescription>
          </CardHeader>
          <CardContent>
            {diffLoading ? (
              <div className="text-sm text-muted-foreground">
                正在计算 diff，请稍候…
              </div>
            ) : (
              <Textarea
                readOnly
                value={diffSql ?? ""}
                className="h-64 font-mono text-xs"
              />
            )}
          </CardContent>
        </Card>
      ) : null}

      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            最近运行
            {latestRun ? (
              <>
                <span className="font-mono text-sm text-muted-foreground">
                  #{latestRun.id}
                </span>
                <StatusBadge status={latestRun.status} />
              </>
            ) : null}
          </CardTitle>
        </CardHeader>
        <CardContent>
          {latestRun ? (
            <LogViewer
              key={latestRun.id}
              runId={latestRun.id}
              live
              emptyText="暂无日志输出"
              onDone={loadRuns}
            />
          ) : (
            <div className="text-sm text-muted-foreground">
              还没有运行记录，点击右上角「运行」启动。
            </div>
          )}
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>运行历史</CardTitle>
        </CardHeader>
        <CardContent>
          {runs.length === 0 ? (
            <div className="text-sm text-muted-foreground">暂无运行历史。</div>
          ) : (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead className="w-16">ID</TableHead>
                  <TableHead>状态</TableHead>
                  <TableHead>开始时间</TableHead>
                  <TableHead>结束时间</TableHead>
                  <TableHead>耗时</TableHead>
                  <TableHead className="w-20"></TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {runs.map((r) => (
                  <TableRow key={r.id}>
                    <TableCell className="font-mono">#{r.id}</TableCell>
                    <TableCell>
                      <StatusBadge status={r.status} />
                    </TableCell>
                    <TableCell>{fmtTime(r.started_at)}</TableCell>
                    <TableCell>{fmtTime(r.finished_at)}</TableCell>
                    <TableCell>{fmtDuration(r.started_at, r.finished_at)}</TableCell>
                    <TableCell>
                      <Button variant="link" size="sm">
                        <Link href={`/runs/${r.id}`}>详情</Link>
                      </Button>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
