"use client";

import { Fragment, useCallback, useEffect, useState } from "react";
import { toast } from "sonner";
import { Plus, Trash2, Pencil, PlugZap } from "lucide-react";
import { api, type Connection } from "@/components/api";
import { fmtTime } from "@/components/format";
import { ConnectionDialog } from "@/components/connection-dialog";
import { ConfirmDialog } from "@/components/confirm-dialog";
import { Button } from "@/components/ui/button";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";

interface TestResult {
  ok: boolean;
  output: string;
}

export default function ConnectionsPage() {
  const [list, setList] = useState<Connection[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [dialogOpen, setDialogOpen] = useState(false);
  const [editing, setEditing] = useState<Connection | null>(null);
  const [deleting, setDeleting] = useState<Connection | null>(null);
  const [deleteLoading, setDeleteLoading] = useState(false);

  const [testingId, setTestingId] = useState<number | null>(null);
  const [testResults, setTestResults] = useState<Record<number, TestResult>>({});
  const [expandedId, setExpandedId] = useState<number | null>(null);

  const load = useCallback(() => {
    api<Connection[]>("/api/connections")
      .then(setList)
      .catch((e) => setError(e instanceof Error ? e.message : "加载失败"))
      .finally(() => setLoading(false));
  }, []);

  useEffect(load, [load]);

  async function testConn(c: Connection) {
    setTestingId(c.id);
    try {
      const res = await api<TestResult>(`/api/connections/${c.id}/test`, {
        method: "POST",
      });
      setTestResults((m) => ({ ...m, [c.id]: res }));
      setExpandedId(c.id);
      if (res.ok) toast.success(`连接「${c.name}」测试成功`);
      else toast.error(`连接「${c.name}」测试失败`);
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "测试失败");
    } finally {
      setTestingId(null);
    }
  }

  async function doDelete() {
    if (!deleting) return;
    setDeleteLoading(true);
    try {
      await api(`/api/connections/${deleting.id}`, { method: "DELETE" });
      toast.success(`已删除连接「${deleting.name}」`);
      setDeleting(null);
      load();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "删除失败");
    } finally {
      setDeleteLoading(false);
    }
  }

  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center justify-between">
        <h1 className="text-xl font-semibold">Connections</h1>
        <Button
          onClick={() => {
            setEditing(null);
            setDialogOpen(true);
          }}
        >
          <Plus className="size-4" />
          新建连接
        </Button>
      </div>

      {loading ? (
        <div className="text-sm text-muted-foreground">加载中…</div>
      ) : error ? (
        <div className="text-sm text-red-500">加载失败：{error}</div>
      ) : list.length === 0 ? (
        <div className="rounded-md border border-dashed p-8 text-center text-sm text-muted-foreground">
          还没有连接，点击右上角「新建连接」添加 MySQL / MariaDB / TiDB 数据源。
        </div>
      ) : (
        <div className="rounded-md border">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>名称</TableHead>
                <TableHead>类型</TableHead>
                <TableHead>Host</TableHead>
                <TableHead>数据库</TableHead>
                <TableHead>创建时间</TableHead>
                <TableHead className="w-56">操作</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {list.map((c) => (
                <Fragment key={c.id}>
                  <TableRow>
                    <TableCell className="font-medium">
                      {c.name}
                      {c.params && c.params !== "{}" ? (
                        <div className="mt-0.5 font-mono text-xs text-muted-foreground">
                          {Object.entries(
                            JSON.parse(c.params) as Record<string, string>
                          )
                            .map(([k, v]) => `${k}=${v}`)
                            .join(" ")}
                        </div>
                      ) : null}
                    </TableCell>
                    <TableCell className="font-mono text-xs">{c.type}</TableCell>
                    <TableCell className="font-mono text-xs">
                      {c.host}:{c.port}
                    </TableCell>
                    <TableCell className="font-mono text-xs">{c.database}</TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      {fmtTime(c.created_at)}
                    </TableCell>
                    <TableCell>
                      <div className="flex gap-1">
                        <Button
                          variant="outline"
                          size="sm"
                          disabled={testingId === c.id}
                          onClick={() => testConn(c)}
                        >
                          <PlugZap className="size-3.5" />
                          {testingId === c.id ? "测试中…" : "测试"}
                        </Button>
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => {
                            setEditing(c);
                            setDialogOpen(true);
                          }}
                        >
                          <Pencil className="size-3.5" />
                          编辑
                        </Button>
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => setDeleting(c)}
                        >
                          <Trash2 className="size-3.5" />
                          删除
                        </Button>
                      </div>
                    </TableCell>
                  </TableRow>
                  {expandedId === c.id && testResults[c.id] ? (
                    <TableRow>
                      <TableCell colSpan={6} className="bg-muted/40">
                        <pre
                          className={
                            "max-h-48 overflow-auto whitespace-pre-wrap break-all rounded p-2 font-mono text-xs " +
                            (testResults[c.id].ok
                              ? "text-green-600 dark:text-green-400"
                              : "text-red-600 dark:text-red-400")
                          }
                        >
                          {testResults[c.id].output ||
                            (testResults[c.id].ok ? "连接成功" : "连接失败")}
                        </pre>
                      </TableCell>
                    </TableRow>
                  ) : null}
                </Fragment>
              ))}
            </TableBody>
          </Table>
        </div>
      )}

      {dialogOpen ? (
        <ConnectionDialog
          key={editing?.id ?? "new"}
          open={dialogOpen}
          onOpenChange={setDialogOpen}
          initial={editing}
          onSaved={load}
        />
      ) : null}
      <ConfirmDialog
        open={!!deleting}
        onOpenChange={(o) => !o && setDeleting(null)}
        title={`删除连接「${deleting?.name ?? ""}」？`}
        description="删除后引用该连接的流水线将无法运行。"
        loading={deleteLoading}
        onConfirm={doDelete}
      />
    </div>
  );
}
