import { useMemo, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "sonner";
import {
  AlertCircle,
  ArrowLeft,
  Check,
  Eye,
  Filter,
  ListChecks,
  Search,
  X,
} from "lucide-react";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Badge, BadgeProps } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Select } from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import { useClaims, useUpdateClaimStatus } from "@/hooks/useClaims";
import { useProject } from "@/hooks/useProjects";
import {
  formatDateTime,
  formatPercent,
  humanizeValue,
  reviewLabel,
} from "@/lib/display";
import { Claim } from "@/lib/api/claims";

function statusVariant(status: string | undefined): BadgeProps["variant"] {
  switch (reviewLabel(status)) {
    case "approved":
      return "success";
    case "rejected":
      return "destructive";
    case "candidate":
      return "warning";
    default:
      return "outline";
  }
}

function confidenceBucket(claim: Claim): string {
  if (typeof claim.confidence !== "number") return "unknown";
  if (claim.confidence >= 0.9) return "auto-approve candidate";
  if (claim.confidence >= 0.7) return "normal review";
  return "priority review";
}

function claimObject(claim: Claim): string {
  return humanizeValue(claim.object ?? claim.object_value);
}

export default function ReviewPage() {
  const navigate = useNavigate();
  const { projectId } = useParams<{ projectId: string }>();
  const projectName = projectId ?? "";
  const { data: project } = useProject(projectName);
  const claims = useClaims(projectName, {
    includeCandidates: true,
    limit: 300,
  });
  const updateStatus = useUpdateClaimStatus(projectName);
  const [statusFilter, setStatusFilter] = useState("all");
  const [search, setSearch] = useState("");
  const [selectedId, setSelectedId] = useState<string | null>(null);

  const filteredClaims = useMemo(() => {
    const query = search.trim().toLowerCase();
    return (claims.data ?? []).filter((claim) => {
      if (statusFilter !== "all" && reviewLabel(claim.status) !== statusFilter) {
        return false;
      }
      if (!query) return true;
      return [
        claim.subject,
        claim.predicate,
        claimObject(claim),
        claim.evidence_text,
        claim.page_url,
        claim.source,
      ]
        .map((value) => humanizeValue(value, "").toLowerCase())
        .some((value) => value.includes(query));
    });
  }, [claims.data, search, statusFilter]);

  const selectedClaim = useMemo(() => {
    return (
      filteredClaims.find((claim) => claim.id === selectedId) ??
      filteredClaims[0]
    );
  }, [filteredClaims, selectedId]);

  const counts = useMemo(() => {
    const all = claims.data ?? [];
    return {
      total: all.length,
      candidate: all.filter((claim) => reviewLabel(claim.status) === "candidate")
        .length,
      approved: all.filter((claim) => reviewLabel(claim.status) === "approved")
        .length,
      rejected: all.filter((claim) => reviewLabel(claim.status) === "rejected")
        .length,
    };
  }, [claims.data]);

  const applyStatus = async (claim: Claim, status: string) => {
    try {
      await updateStatus.mutateAsync({
        claimId: claim.id,
        status,
        reason:
          status === "rejected"
            ? "Rejected from Claim Review"
            : "Updated from Claim Review",
      });
      toast.success(`Claim ${status}`);
    } catch (error) {
      toast.error((error as Error).message);
    }
  };

  return (
    <div className="mx-auto max-w-7xl px-6 py-8">
      <div className="mb-6 flex items-center gap-3">
        <Button
          variant="ghost"
          size="icon"
          onClick={() => navigate(`/schema/${projectName}`)}
          aria-label="Back"
        >
          <ArrowLeft className="h-4 w-4" />
        </Button>
        <div className="flex-1">
          <h1 className="flex items-center gap-2 text-2xl font-bold tracking-tight">
            <ListChecks className="h-6 w-6 text-primary" />
            Claim Review
          </h1>
          <p className="text-sm text-muted-foreground">
            {project?.name ?? projectName} · 후보, 승인, 반려 상태 분리 검토
          </p>
        </div>
        <Button onClick={() => navigate(`/quality/${projectName}`)}>
          Quality Inspector
        </Button>
      </div>

      {claims.isError && (
        <Card className="mb-6 border-destructive">
          <CardContent className="flex items-center gap-2 py-4 text-sm text-destructive">
            <AlertCircle className="h-4 w-4" />
            {(claims.error as Error).message}
          </CardContent>
        </Card>
      )}

      <div className="mb-6 grid gap-4 md:grid-cols-4">
        <Metric label="Total" value={counts.total} />
        <Metric label="Candidate" value={counts.candidate} />
        <Metric label="Approved" value={counts.approved} />
        <Metric label="Rejected" value={counts.rejected} />
      </div>

      <div className="grid gap-6 lg:grid-cols-[1fr_420px]">
        <Card>
          <CardHeader>
            <div className="flex flex-wrap items-center justify-between gap-3">
              <div>
                <CardTitle>Review Queue</CardTitle>
                <CardDescription>
                  신뢰도, 출처, 생성 방식, 검증 결과를 함께 확인합니다.
                </CardDescription>
              </div>
              <div className="flex min-w-0 flex-wrap gap-2">
                <div className="relative">
                  <Search className="pointer-events-none absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
                  <Input
                    value={search}
                    onChange={(event) => setSearch(event.target.value)}
                    className="w-56 pl-9"
                    placeholder="Search claims"
                  />
                </div>
                <div className="relative">
                  <Filter className="pointer-events-none absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
                  <Select
                    value={statusFilter}
                    onChange={(event) => setStatusFilter(event.target.value)}
                    className="w-40 pl-9"
                  >
                    <option value="all">All</option>
                    <option value="candidate">Candidate</option>
                    <option value="approved">Approved</option>
                    <option value="rejected">Rejected</option>
                  </Select>
                </div>
              </div>
            </div>
          </CardHeader>
          <CardContent>
            {claims.isLoading && (
              <div className="space-y-3">
                {Array.from({ length: 5 }).map((_, index) => (
                  <Skeleton key={index} className="h-24" />
                ))}
              </div>
            )}
            {!claims.isLoading && filteredClaims.length === 0 && (
              <p className="py-10 text-center text-sm text-muted-foreground">
                조건에 맞는 클레임이 없습니다.
              </p>
            )}
            <div className="space-y-3">
              {filteredClaims.map((claim) => (
                <article
                  key={claim.id}
                  className="rounded-md border bg-background p-4"
                >
                  <div className="flex flex-wrap items-start justify-between gap-3">
                    <button
                      type="button"
                      onClick={() => setSelectedId(claim.id)}
                      className="min-w-0 flex-1 text-left"
                    >
                      <div className="mb-2 flex flex-wrap items-center gap-2">
                        <Badge variant={statusVariant(claim.status)}>
                          {reviewLabel(claim.status)}
                        </Badge>
                        <Badge variant="secondary">{claim.predicate}</Badge>
                        <span className="text-xs text-muted-foreground">
                          {confidenceBucket(claim)}
                        </span>
                      </div>
                      <div className="flex flex-wrap items-center gap-2 text-sm">
                        <span className="font-medium">
                          {humanizeValue(claim.subject)}
                        </span>
                        <span className="text-muted-foreground">-&gt;</span>
                        <span className="font-medium">{claimObject(claim)}</span>
                      </div>
                      <div className="mt-2 flex flex-wrap gap-2 text-xs text-muted-foreground">
                        <span>Confidence {formatPercent(claim.confidence)}</span>
                        <span>Source {humanizeValue(claim.source)}</span>
                        <span>
                          Evidence {claim.evidence_text ? "yes" : "missing"}
                        </span>
                        <span>
                          Method {humanizeValue(claim.extraction_method)}
                        </span>
                      </div>
                    </button>
                    <div className="flex gap-1">
                      <Button
                        variant="outline"
                        size="sm"
                        onClick={() => setSelectedId(claim.id)}
                      >
                        <Eye className="h-4 w-4" />
                        Detail
                      </Button>
                      <Button
                        variant="outline"
                        size="sm"
                        onClick={() => applyStatus(claim, "validated_claim")}
                        disabled={updateStatus.isPending}
                      >
                        <Check className="h-4 w-4" />
                        Approve
                      </Button>
                      <Button
                        variant="outline"
                        size="sm"
                        onClick={() => applyStatus(claim, "rejected")}
                        disabled={updateStatus.isPending}
                      >
                        <X className="h-4 w-4" />
                        Reject
                      </Button>
                    </div>
                  </div>
                </article>
              ))}
            </div>
          </CardContent>
        </Card>

        <aside className="lg:sticky lg:top-4 lg:self-start">
          <Card>
            <CardHeader>
              <CardTitle>Claim Detail</CardTitle>
              <CardDescription>
                근거, 출처, 검증 결과, 히스토리
              </CardDescription>
            </CardHeader>
            <CardContent>
              {!selectedClaim && (
                <p className="py-8 text-center text-sm text-muted-foreground">
                  클레임을 선택하세요.
                </p>
              )}
              {selectedClaim && (
                <div className="space-y-4">
                  <div className="flex flex-wrap gap-2">
                    <Badge variant={statusVariant(selectedClaim.status)}>
                      {reviewLabel(selectedClaim.status)}
                    </Badge>
                    <Badge variant="outline">
                      {formatPercent(selectedClaim.confidence)}
                    </Badge>
                    {selectedClaim.review_required && (
                      <Badge variant="warning">review required</Badge>
                    )}
                  </div>
                  <DetailRow label="Subject" value={selectedClaim.subject} />
                  <DetailRow label="Subject Type" value={selectedClaim.subject_type} />
                  <DetailRow label="Predicate" value={selectedClaim.predicate} />
                  <DetailRow
                    label="Object"
                    value={selectedClaim.object ?? selectedClaim.object_value}
                  />
                  <DetailRow label="Source" value={selectedClaim.source} />
                  <DetailRow label="Source URL" value={selectedClaim.page_url} />
                  <DetailRow
                    label="Page Type"
                    value={selectedClaim.page_type}
                  />
                  <DetailRow
                    label="Created By"
                    value={selectedClaim.extraction_method}
                  />
                  <DetailRow
                    label="Validation"
                    value={
                      selectedClaim.validation_status ??
                      selectedClaim.graph_merge_status
                    }
                  />
                  {selectedClaim.graph_merge_reason && (
                    <DetailRow
                      label="Graph Reason"
                      value={selectedClaim.graph_merge_reason}
                    />
                  )}
                  {selectedClaim.evidence_text && (
                    <section>
                      <h3 className="mb-2 text-sm font-medium">Evidence Text</h3>
                      <div className="rounded-md bg-yellow-50 px-3 py-2 text-sm leading-relaxed text-yellow-950">
                        {selectedClaim.evidence_text}
                      </div>
                    </section>
                  )}
                  {selectedClaim.confidence_breakdown && (
                    <section>
                      <h3 className="mb-2 text-sm font-medium">
                        Confidence Breakdown
                      </h3>
                      <pre className="max-h-44 overflow-auto rounded-md bg-secondary/30 p-3 text-xs">
                        {JSON.stringify(
                          selectedClaim.confidence_breakdown,
                          null,
                          2,
                        )}
                      </pre>
                    </section>
                  )}
                  {selectedClaim.source_history &&
                    selectedClaim.source_history.length > 0 && (
                      <section>
                        <h3 className="mb-2 text-sm font-medium">
                          Source History
                        </h3>
                        <pre className="max-h-44 overflow-auto rounded-md bg-secondary/30 p-3 text-xs">
                          {JSON.stringify(selectedClaim.source_history, null, 2)}
                        </pre>
                      </section>
                    )}
                  <div className="grid grid-cols-2 gap-2 pt-2">
                    <Button
                      onClick={() =>
                        applyStatus(selectedClaim, "validated_claim")
                      }
                      disabled={updateStatus.isPending}
                    >
                      <Check className="h-4 w-4" />
                      Approve
                    </Button>
                    <Button
                      variant="outline"
                      onClick={() => applyStatus(selectedClaim, "rejected")}
                      disabled={updateStatus.isPending}
                    >
                      <X className="h-4 w-4" />
                      Reject
                    </Button>
                  </div>
                  <div className="text-xs text-muted-foreground">
                    Last seen {formatDateTime(selectedClaim.last_seen_at)}
                  </div>
                </div>
              )}
            </CardContent>
          </Card>
        </aside>
      </div>
    </div>
  );
}

function Metric({ label, value }: { label: string; value: number }) {
  return (
    <Card>
      <CardContent className="py-4">
        <div className="text-xs text-muted-foreground">{label}</div>
        <div className="mt-1 text-2xl font-semibold">
          {value.toLocaleString()}
        </div>
      </CardContent>
    </Card>
  );
}

function DetailRow({ label, value }: { label: string; value: unknown }) {
  return (
    <div className="rounded-md border bg-background px-3 py-2 text-sm">
      <div className="text-xs text-muted-foreground">{label}</div>
      <div className="mt-1 break-words font-medium">{humanizeValue(value)}</div>
    </div>
  );
}
