"use client";

/**
 * 批量测试用例详情面板。
 * 与 prompt mode DebugDrawer overlay 相同：作为右侧 flex 半屏，无遮罩/模糊。
 */

import {
  CheckCircle2,
  Circle,
  Loader2,
  MessageSquareText,
  Pencil,
  RotateCcw,
  Target,
  TriangleAlert,
  Wrench,
  X,
} from "lucide-react";
import { useEffect, useRef } from "react";

import { BatchCaseStatusBadge } from "@/components/batch-test/batch-case-status";
import { Button } from "@/components/ui/button";
import {
  firstEvaluationFailureReason,
  type BatchEvaluationResult,
  type BatchRunCase,
  type BatchToolCallRecord,
  type BatchTurnResult,
} from "@/data/batch-run";
import { cn } from "@/lib/utils";

type BatchCaseDetailDrawerProps = {
  item: BatchRunCase;
  assistantName: string;
  onClose: () => void;
  onEdit?: () => void;
  onRerun?: () => void;
};

export function BatchCaseDetailDrawer({
  item,
  assistantName,
  onClose,
  onEdit,
  onRerun,
}: BatchCaseDetailDrawerProps) {
  const closeButtonRef = useRef<HTMLButtonElement>(null);
  const failureReason = firstEvaluationFailureReason(item);

  useEffect(() => {
    closeButtonRef.current?.focus();
  }, [item.id]);

  return (
    <aside
      id="batch-case-detail"
      role="complementary"
      aria-labelledby="batch-case-detail-title"
      className="flex h-full min-w-0 flex-1 flex-col overflow-hidden border-l border-hairline bg-card"
    >
      <div className="flex min-h-14 shrink-0 items-center gap-3 border-b border-hairline px-4 py-3">
        <button
          ref={closeButtonRef}
          type="button"
          aria-label="关闭用例详情"
          title="关闭"
          className="flex size-10 shrink-0 items-center justify-center rounded-full border border-hairline-strong bg-card text-muted-foreground shadow-sm transition-colors hover:text-foreground"
          onClick={onClose}
        >
          <X size={16} />
        </button>
        <div className="min-w-0 flex-1">
          <h2
            id="batch-case-detail-title"
            className="truncate text-sm font-medium text-foreground"
          >
            {item.name}
          </h2>
          <p className="truncate text-xs text-muted-soft">
            被测助手：{assistantName} · Pipeline 结果
          </p>
        </div>
        <BatchCaseStatusBadge status={item.status} />
      </div>

      <div className="min-h-0 flex-1 overflow-y-auto px-5 py-5">
        <div className="space-y-5">
          <section className="rounded-2xl border border-hairline bg-canvas-soft px-4 py-3.5">
            <p className="text-xs text-muted-soft">当前状态</p>
            <p className="mt-1 text-sm text-muted-foreground">
              {statusDescription(item)}
            </p>
          </section>

          {(item.status === "waiting" || item.status === "running") && (
            <>
              <section className="rounded-2xl border border-hairline bg-canvas-soft px-4 py-3.5">
                <p className="text-xs font-medium text-foreground">执行契约</p>
                <p className="mt-1 text-xs leading-5 text-muted-soft">
                  正在执行固定文字脚本；完成后将展示每一轮回复、工具调用和全部评估标准。
                </p>
              </section>
              <ExecutionTimeline status={item.status} />
            </>
          )}

          {item.status === "error" && item.executionError && (
            <section>
              <div className="flex items-center gap-2 text-sm font-medium text-amber-600 dark:text-amber-400">
                <TriangleAlert size={16} />
                <h3>执行错误</h3>
              </div>
              <div className="mt-2.5 rounded-2xl border border-amber-500/25 bg-amber-500/[0.06] px-4 py-3.5">
                <div className="flex flex-wrap items-center gap-2">
                  <code className="text-xs font-medium text-foreground">
                    {item.executionError.code}
                  </code>
                  <span className="rounded-full border border-amber-500/25 px-2 py-0.5 text-[10px] text-amber-600 dark:text-amber-400">
                    {item.executionError.stage}
                  </span>
                </div>
                <p className="mt-2 text-sm leading-6 text-muted-foreground">
                  {item.executionError.message}
                </p>
                <p className="mt-2 text-xs text-muted-soft">
                  已尝试 {item.attemptCount} 次（包含首次执行），重试后仍未恢复。
                </p>
              </div>
            </section>
          )}

          {(item.status === "pass" || item.status === "fail") && (
            <>
              <section>
                <div className="flex items-center gap-2 text-sm font-medium text-foreground">
                  <MessageSquareText size={16} />
                  <h3>逐轮执行结果</h3>
                </div>
                <div className="mt-3 space-y-3">
                  {item.turns.map((turn) => (
                    <TurnResultCard key={turn.id} turn={turn} />
                  ))}
                </div>
              </section>

              {item.overallCriteria.length > 0 && (
                <section>
                  <div className="flex items-center gap-2 text-sm font-medium text-foreground">
                    <Target size={16} />
                    <h3>整体评估标准</h3>
                  </div>
                  <div className="mt-3 space-y-2">
                    {item.overallCriteria.map((evaluation) => (
                      <EvaluationCard
                        key={evaluation.id}
                        evaluation={evaluation}
                      />
                    ))}
                  </div>
                </section>
              )}
            </>
          )}

          {item.status === "fail" && failureReason && (
            <DetailSection
              icon={<TriangleAlert size={16} />}
              title="失败原因"
              value={failureReason}
              tone="destructive"
            />
          )}

          {item.status === "skipped" && (
            <div className="rounded-2xl border border-dashed border-hairline-strong px-4 py-4 text-sm leading-6 text-muted-foreground">
              该用例未执行，因此没有实际回复与判断结果。
            </div>
          )}
        </div>
      </div>

      {(onEdit || onRerun) && (
        <div className="flex shrink-0 items-center justify-end gap-2 border-t border-hairline bg-card px-5 py-3">
          {onEdit && (
            <Button
              type="button"
              variant="outline"
              className="gap-2 rounded-full border-hairline-strong"
              onClick={onEdit}
            >
              <Pencil size={14} />
              编辑用例
            </Button>
          )}
          {onRerun && (
            <Button
              type="button"
              className="gap-2 rounded-full"
              onClick={onRerun}
            >
              <RotateCcw size={14} />
              仅重跑此项
            </Button>
          )}
        </div>
      )}
    </aside>
  );
}

function statusDescription(item: BatchRunCase): string {
  if (item.status === "waiting") {
    return item.attemptCount > 0
      ? `第 ${item.attemptCount} 次执行发生错误，正在等待重试。`
      : "已加入执行队列，正在等待可用并发。";
  }
  if (item.status === "running") {
    return item.attemptCount > 1
      ? `正在进行第 ${item.attemptCount} 次尝试。`
      : "正在请求助手响应，结果尚未生成。";
  }
  if (item.status === "pass") return "执行与结果判断均已完成。";
  if (item.status === "fail") return "执行完成，但实际回复未达到预期。";
  if (item.status === "error") return "执行未完成，已用尽配置的重试次数。";
  return "本轮运行已结束，该用例未执行。";
}

function TurnResultCard({ turn }: { turn: BatchTurnResult }) {
  return (
    <article className="overflow-hidden rounded-2xl border border-hairline bg-canvas-soft/60">
      <div className="border-b border-hairline px-4 py-3">
        <p className="text-xs font-medium text-foreground">
          第 {turn.index + 1} 轮
        </p>
        <div className="mt-2 grid gap-2 text-xs leading-5 sm:grid-cols-[72px_minmax(0,1fr)]">
          <span className="text-muted-soft">用户输入</span>
          <p className="whitespace-pre-wrap text-muted-foreground">
            {turn.userInput}
          </p>
          <span className="text-muted-soft">Agent 回复</span>
          <p className="whitespace-pre-wrap text-muted-foreground">
            {turn.assistantReply}
          </p>
        </div>
      </div>

      {turn.toolCalls.length > 0 && (
        <div className="space-y-2 border-b border-hairline px-4 py-3">
          <p className="inline-flex items-center gap-1.5 text-xs font-medium text-foreground">
            <Wrench size={13} />
            工具调用记录
          </p>
          {turn.toolCalls.map((toolCall) => (
            <ToolCallCard key={toolCall.id} toolCall={toolCall} />
          ))}
        </div>
      )}

      <div className="space-y-2 px-4 py-3">
        {turn.evaluations.length === 0 ? (
          <p className="text-xs text-muted-soft">本轮仅推动对话，不执行评估。</p>
        ) : (
          turn.evaluations.map((evaluation) => (
            <EvaluationCard key={evaluation.id} evaluation={evaluation} />
          ))
        )}
      </div>
    </article>
  );
}

function ToolCallCard({ toolCall }: { toolCall: BatchToolCallRecord }) {
  return (
    <div className="rounded-xl border border-violet-500/20 bg-background/70 p-2.5">
      <div className="flex flex-wrap items-center gap-2">
        <code className="text-xs text-foreground">{toolCall.functionName}</code>
        <span className="rounded-full border border-hairline px-2 py-0.5 text-[10px] text-muted-soft">
          {toolCall.outcome === "success" ? "成功" : "错误"} ·{" "}
          {toolCall.durationMs} ms
        </span>
      </div>
      <div className="mt-2 grid gap-2 sm:grid-cols-2">
        <CodeResult label="参数" value={toolCall.argumentsJson} />
        <CodeResult label="工具返回" value={toolCall.resultJson} />
      </div>
    </div>
  );
}

function CodeResult({ label, value }: { label: string; value: string }) {
  return (
    <div className="min-w-0">
      <p className="mb-1 text-[10px] text-muted-soft">{label}</p>
      <pre className="max-h-36 overflow-auto whitespace-pre-wrap break-all rounded-lg bg-canvas-soft p-2 font-mono text-[10px] leading-4 text-muted-foreground">
        {value}
      </pre>
    </div>
  );
}

function EvaluationCard({
  evaluation,
}: {
  evaluation: BatchEvaluationResult;
}) {
  const passed = evaluation.status === "pass";
  return (
    <div
      className={cn(
        "rounded-xl border bg-background/70 p-3",
        passed ? "border-hairline" : "border-destructive/30 bg-destructive/5",
      )}
    >
      <div className="flex items-center gap-2">
        {passed ? (
          <CheckCircle2 size={14} className="shrink-0 text-success" />
        ) : (
          <TriangleAlert size={14} className="shrink-0 text-destructive" />
        )}
        <p className="min-w-0 flex-1 text-xs font-medium text-foreground">
          {evaluation.label}
        </p>
        <span
          className={cn(
            "text-[10px] font-medium",
            passed ? "text-success" : "text-destructive",
          )}
        >
          {passed ? "通过" : "失败"}
        </span>
      </div>
      <dl className="mt-2 grid gap-x-2 gap-y-1 text-[11px] leading-4 sm:grid-cols-[52px_minmax(0,1fr)]">
        <dt className="text-muted-soft">预期</dt>
        <dd className="whitespace-pre-wrap text-muted-foreground">
          {evaluation.expected}
        </dd>
        <dt className="text-muted-soft">实际</dt>
        <dd className="whitespace-pre-wrap text-muted-foreground">
          {evaluation.actual}
        </dd>
        {evaluation.reason && (
          <>
            <dt className="text-destructive">原因</dt>
            <dd className="text-foreground">{evaluation.reason}</dd>
          </>
        )}
      </dl>
    </div>
  );
}

function DetailSection({
  icon,
  title,
  value,
  tone = "default",
}: {
  icon: React.ReactNode;
  title: string;
  value: string;
  tone?: "default" | "destructive";
}) {
  return (
    <section>
      <div
        className={cn(
          "flex items-center gap-2 text-sm font-medium text-foreground",
          tone === "destructive" && "text-destructive",
        )}
      >
        {icon}
        <h3>{title}</h3>
      </div>
      <p
        className={cn(
          "mt-2.5 rounded-2xl border border-hairline bg-canvas-soft px-4 py-3.5 text-sm leading-6 text-muted-foreground",
          tone === "destructive" &&
            "border-destructive/20 bg-destructive/5 text-foreground",
        )}
      >
        {value}
      </p>
    </section>
  );
}

function ExecutionTimeline({ status }: { status: "waiting" | "running" }) {
  const isRunning = status === "running";
  const steps = [
    {
      label: "载入测试上下文",
      detail: isRunning ? "已完成" : "等待开始",
      state: isRunning ? "done" : "pending",
    },
    {
      label: "请求助手响应",
      detail: isRunning ? "Pipeline 生成中" : "尚未开始",
      state: isRunning ? "active" : "pending",
    },
    {
      label: "执行结果判断",
      detail: "尚未开始",
      state: "pending",
    },
  ] as const;

  return (
    <section>
      <div className="flex items-center gap-2 text-sm font-medium text-foreground">
        <Loader2 size={16} className={cn(isRunning && "animate-spin")} />
        <h3>执行进度</h3>
      </div>
      <ol className="mt-3 rounded-2xl border border-hairline px-4 py-1">
        {steps.map((step) => (
          <li
            key={step.label}
            className="flex items-center gap-3 border-b border-hairline py-3.5 last:border-b-0"
          >
            {step.state === "done" ? (
              <CheckCircle2 size={17} className="shrink-0 text-success" />
            ) : step.state === "active" ? (
              <Loader2 size={17} className="shrink-0 animate-spin text-primary" />
            ) : (
              <Circle size={17} className="shrink-0 text-muted-soft" />
            )}
            <span className="min-w-0 flex-1 text-sm text-foreground">
              {step.label}
            </span>
            <span className="text-xs text-muted-soft">{step.detail}</span>
          </li>
        ))}
      </ol>
    </section>
  );
}
