import { useEffect, useMemo, useState } from "react";
import { useAuth } from "@/_core/hooks/useAuth";
import { trpc } from "@/lib/trpc";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Skeleton } from "@/components/ui/skeleton";
import { formatDateTimeShanghai } from "@/lib/time";
import { toast } from "sonner";
import { useBackgroundTask } from "@/hooks/useBackgroundTask";
import { Database, Image as ImageIcon, Loader2, Microscope, ShieldCheck, Sparkles } from "lucide-react";

type ReferenceImage = {
  id: number;
  slug: string;
  title: string;
  exerciseType: string;
  imageUrl: string;
  sourcePageUrl: string;
  sourceLabel: string;
  author: string | null;
  license: string | null;
  expectedFocus: string[] | null;
  tags: string[] | null;
  notes: string | null;
};

type VisionRun = {
  id: number;
  taskId: string;
  userId: number;
  userName: string | null;
  referenceImageId: number | null;
  referenceTitle: string | null;
  title: string;
  exerciseType: string;
  imageUrl: string;
  status: "queued" | "succeeded" | "failed";
  visionStatus: "pending" | "ok" | "fallback" | "failed";
  configuredModel: string | null;
  expectedFocus: string[] | null;
  summary: string | null;
  corrections: string | null;
  warning: string | null;
  error: string | null;
  createdAt: Date;
  updatedAt: Date;
};

const COMMONS_SPECIAL_FILE_PATH = "/wiki/Special:FilePath/";
const COMMONS_FILE_PAGE_PATH = "/wiki/File:";

function getCompressedVisionImageUrl(imageUrl: string, width = 960) {
  try {
    const url = new URL(imageUrl);
    if (url.hostname !== "commons.wikimedia.org") {
      return imageUrl;
    }

    let fileName: string | null = null;
    if (url.pathname.startsWith(COMMONS_SPECIAL_FILE_PATH)) {
      fileName = url.pathname.slice(COMMONS_SPECIAL_FILE_PATH.length);
    } else if (url.pathname.startsWith(COMMONS_FILE_PAGE_PATH)) {
      fileName = url.pathname.slice(COMMONS_FILE_PAGE_PATH.length);
    }

    if (!fileName) {
      return imageUrl;
    }

    const decodedFileName = decodeURIComponent(fileName);
    return `https://commons.wikimedia.org/wiki/Special:Redirect/file/${encodeURIComponent(decodedFileName)}?width=${width}`;
  } catch {
    return imageUrl;
  }
}

function VisionPreviewImage({
  src,
  alt,
  className,
  width = 960,
}: {
  src: string;
  alt: string;
  className: string;
  width?: number;
}) {
  const [displaySrc, setDisplaySrc] = useState(() => getCompressedVisionImageUrl(src, width));

  useEffect(() => {
    setDisplaySrc(getCompressedVisionImageUrl(src, width));
  }, [src, width]);

  return (
    <img
      src={displaySrc}
      alt={alt}
      className={className}
      loading="lazy"
      referrerPolicy="no-referrer"
      onError={() => {
        if (displaySrc !== src) {
          setDisplaySrc(src);
        }
      }}
    />
  );
}

function statusBadge(run: VisionRun) {
  if (run.status === "failed" || run.visionStatus === "failed") {
    return <Badge variant="destructive">失败</Badge>;
  }
  if (run.status === "queued" || run.visionStatus === "pending") {
    return <Badge variant="secondary">排队中</Badge>;
  }
  if (run.visionStatus === "fallback") {
    return <Badge variant="outline">文本降级</Badge>;
  }
  return <Badge className="bg-emerald-600 hover:bg-emerald-600">视觉成功</Badge>;
}

export default function VisionLab() {
  const { user } = useAuth();
  const utils = trpc.useUtils();
  const [activeTaskId, setActiveTaskId] = useState<string | null>(null);
  const activeTask = useBackgroundTask(activeTaskId);

  const libraryQuery = trpc.vision.library.useQuery();
  const runsQuery = trpc.vision.runs.useQuery(
    { limit: 50 },
    { refetchInterval: 4000 }
  );

  const seedMutation = trpc.vision.seedLibrary.useMutation({
    onSuccess: (data) => {
      toast.success(`标准图库已就绪，共 ${data.count} 张`);
      utils.vision.library.invalidate();
    },
    onError: (error) => toast.error(`标准图库初始化失败: ${error.message}`),
  });

  const runReferenceMutation = trpc.vision.runReference.useMutation({
    onSuccess: (data) => {
      setActiveTaskId(data.taskId);
      toast.success("视觉测试任务已提交");
      utils.vision.runs.invalidate();
    },
    onError: (error) => toast.error(`视觉测试提交失败: ${error.message}`),
  });

  const runAllMutation = trpc.vision.runAll.useMutation({
    onSuccess: (data) => {
      toast.success(`已提交 ${data.count} 个视觉测试任务`);
      if (data.queued[0]?.taskId) {
        setActiveTaskId(data.queued[0].taskId);
      }
      utils.vision.runs.invalidate();
    },
    onError: (error) => toast.error(`批量视觉测试提交失败: ${error.message}`),
  });

  const retryRunMutation = trpc.vision.retryRun.useMutation({
    onSuccess: () => {
      toast.success("视觉记录已重新加入队列");
      utils.vision.runs.invalidate();
    },
    onError: (error) => toast.error(`重新执行失败: ${error.message}`),
  });

  const retryFallbacksMutation = trpc.vision.retryFallbacks.useMutation({
    onSuccess: (data) => {
      toast.success(`已重新排队 ${data.count} 条历史视觉记录`);
      utils.vision.runs.invalidate();
    },
    onError: (error) => toast.error(`批量修复失败: ${error.message}`),
  });

  useEffect(() => {
    if (activeTask.data?.status === "succeeded" || activeTask.data?.status === "failed") {
      utils.vision.runs.invalidate();
      setActiveTaskId(null);
    }
  }, [activeTask.data, utils.vision.runs]);

  const references = useMemo(() => (libraryQuery.data ?? []) as ReferenceImage[], [libraryQuery.data]);
  const runs = useMemo(() => (runsQuery.data ?? []) as VisionRun[], [runsQuery.data]);

  if (libraryQuery.isLoading && runsQuery.isLoading) {
    return (
      <div className="space-y-6">
        <Skeleton className="h-28 w-full" />
        <Skeleton className="h-64 w-full" />
        <Skeleton className="h-64 w-full" />
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
        <div>
          <h1 className="text-2xl font-bold tracking-tight">视觉标准图库</h1>
          <p className="text-sm text-muted-foreground mt-1">
            用公网可访问的网球标准图验证多模态纠正链路，并持久化每次测试结果。
          </p>
        </div>
        <div className="flex flex-wrap gap-2">
          {user?.role === "admin" ? (
            <>
              <Button
                variant="outline"
                onClick={() => seedMutation.mutate()}
                disabled={seedMutation.isPending}
                className="gap-2"
              >
                {seedMutation.isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Database className="h-4 w-4" />}
                初始化标准库
              </Button>
              <Button
                variant="outline"
                onClick={() => retryFallbacksMutation.mutate({ limit: 20 })}
                disabled={retryFallbacksMutation.isPending}
                className="gap-2"
              >
                {retryFallbacksMutation.isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Sparkles className="h-4 w-4" />}
                修复历史降级
              </Button>
            </>
          ) : null}
          <Button
            onClick={() => runAllMutation.mutate()}
            disabled={runAllMutation.isPending || references.length === 0}
            className="gap-2"
          >
            {runAllMutation.isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Microscope className="h-4 w-4" />}
            批量跑测试
          </Button>
        </div>
      </div>

      {user?.role === "admin" ? (
        <Alert>
          <ShieldCheck className="h-4 w-4" />
          <AlertTitle>Admin 视角</AlertTitle>
          <AlertDescription>
            当前账号可查看全部视觉测试记录。若用户名为 `H1` 且被配置进 `ADMIN_USERNAMES`，登录后会自动拥有此视角。
          </AlertDescription>
        </Alert>
      ) : (
        <Alert>
          <ImageIcon className="h-4 w-4" />
          <AlertTitle>个人测试视角</AlertTitle>
          <AlertDescription>当前页面展示标准图库，以及你自己提交的视觉测试结果。</AlertDescription>
        </Alert>
      )}

      {activeTask.data?.status === "queued" || activeTask.data?.status === "running" ? (
        <Alert>
          <Sparkles className="h-4 w-4" />
          <AlertTitle>后台执行中</AlertTitle>
          <AlertDescription>{activeTask.data.message || "视觉测试正在后台执行。"}</AlertDescription>
        </Alert>
      ) : null}

      <section className="space-y-4">
        <div className="flex items-center justify-between">
          <h2 className="text-lg font-semibold">标准图片库</h2>
          <Badge variant="secondary">{references.length} 张</Badge>
        </div>
        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          {references.map((reference) => (
            <Card key={reference.id} className="overflow-hidden border-0 shadow-sm">
              <div className="aspect-[4/3] overflow-hidden bg-muted">
                <VisionPreviewImage
                  src={reference.imageUrl}
                  alt={reference.title}
                  className="h-full w-full object-cover"
                  width={960}
                />
              </div>
              <CardHeader className="pb-3">
                <CardTitle className="text-base">{reference.title}</CardTitle>
                <CardDescription className="flex flex-wrap gap-2">
                  <Badge variant="outline">{reference.exerciseType}</Badge>
                  {reference.license ? <Badge variant="secondary">{reference.license}</Badge> : null}
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-3">
                {reference.notes ? (
                  <p className="text-sm text-muted-foreground">{reference.notes}</p>
                ) : null}
                {reference.expectedFocus?.length ? (
                  <div className="flex flex-wrap gap-2">
                    {reference.expectedFocus.map((item) => (
                      <Badge key={item} variant="outline">{item}</Badge>
                    ))}
                  </div>
                ) : null}
                <div className="flex items-center justify-between gap-3">
                  <a
                    href={reference.sourcePageUrl}
                    target="_blank"
                    rel="noreferrer"
                    className="text-sm text-primary underline-offset-4 hover:underline"
                  >
                    来源页
                  </a>
                  <Button
                    size="sm"
                    className="gap-2"
                    onClick={() => runReferenceMutation.mutate({ referenceImageId: reference.id })}
                    disabled={runReferenceMutation.isPending}
                  >
                    {runReferenceMutation.isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Microscope className="h-4 w-4" />}
                    运行测试
                  </Button>
                </div>
              </CardContent>
            </Card>
          ))}
        </div>
      </section>

      <section className="space-y-4">
        <div className="flex items-center justify-between">
          <h2 className="text-lg font-semibold">视觉测试记录</h2>
          <Badge variant="secondary">{runs.length} 条</Badge>
        </div>
        <div className="grid gap-4">
          {runs.map((run) => (
            <Card key={run.id} className="border-0 shadow-sm">
              <CardContent className="pt-5 space-y-3">
                <div className="flex flex-col gap-4 lg:flex-row">
                  <a
                    href={run.imageUrl}
                    target="_blank"
                    rel="noreferrer"
                    className="block overflow-hidden rounded-xl bg-muted lg:w-72 lg:flex-none"
                  >
                    <div className="aspect-[4/3]">
                      <VisionPreviewImage
                        src={run.imageUrl}
                        alt={run.title}
                        className="h-full w-full object-cover"
                        width={720}
                      />
                    </div>
                  </a>

                  <div className="min-w-0 flex-1 space-y-3">
                    <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
                      <div className="space-y-1">
                        <div className="flex flex-wrap items-center gap-2">
                          <h3 className="font-semibold">{run.title}</h3>
                          {statusBadge(run)}
                          <Badge variant="outline">{run.exerciseType}</Badge>
                        </div>
                        <p className="text-xs text-muted-foreground">
                          {formatDateTimeShanghai(run.createdAt)}
                          {user?.role === "admin" && run.userName ? ` · 提交人：${run.userName}` : ""}
                        </p>
                      </div>
                      {run.configuredModel ? (
                        <Badge variant="secondary">{run.configuredModel}</Badge>
                      ) : null}
                    </div>

                    {run.summary ? <p className="text-sm">{run.summary}</p> : null}
                    {run.warning ? (
                      <p className="text-sm text-amber-700">降级说明：{run.warning}</p>
                    ) : null}
                    {run.error ? (
                      <p className="text-sm text-destructive">错误：{run.error}</p>
                    ) : null}

                    {(run.visionStatus === "fallback" || run.status === "failed") ? (
                      <div className="flex justify-end">
                        <Button
                          size="sm"
                          variant="outline"
                          className="gap-2"
                          onClick={() => retryRunMutation.mutate({ runId: run.id })}
                          disabled={retryRunMutation.isPending}
                        >
                          {retryRunMutation.isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : <Microscope className="h-4 w-4" />}
                          重新视觉识别
                        </Button>
                      </div>
                    ) : null}

                    {run.expectedFocus?.length ? (
                      <div className="flex flex-wrap gap-2">
                        {run.expectedFocus.map((item) => (
                          <Badge key={item} variant="outline">{item}</Badge>
                        ))}
                      </div>
                    ) : null}

                    {run.corrections ? (
                      <div className="rounded-xl bg-muted/50 p-3 text-sm leading-6 whitespace-pre-wrap">
                        {run.corrections}
                      </div>
                    ) : null}
                  </div>
                </div>
              </CardContent>
            </Card>
          ))}
          {runs.length === 0 ? (
            <Card className="border-dashed">
              <CardContent className="pt-6 text-sm text-muted-foreground">
                还没有视觉测试记录。先运行一张标准图测试，结果会自动入库并显示在这里。
              </CardContent>
            </Card>
          ) : null}
        </div>
      </section>
    </div>
  );
}
