import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  AlertTriangle,
  CheckCircle2,
  Database,
  ShieldAlert,
} from "lucide-react";
import { useState } from "react";
import { RoleGuard } from "../../components/auth/RoleGuard";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
  type DataIntegrityCheck,
  type DataIntegrityStatus,
  type OrphanUserLoginID,
  deleteOrphanUserLoginIDs,
  fetchDataIntegrityReport,
  fetchOrphanUserLoginIDs,
} from "../../lib/adminApi";

function statusLabel(status: DataIntegrityStatus) {
  switch (status) {
    case "pass":
      return "정상";
    case "warning":
      return "주의";
    case "fail":
      return "실패";
    default:
      return status;
  }
}

function statusBadgeVariant(status: DataIntegrityStatus) {
  switch (status) {
    case "pass":
      return "success";
    case "warning":
      return "warning";
    default:
      return "warning";
  }
}

function formatDateTime(value?: string) {
  if (!value) return "-";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return new Intl.DateTimeFormat("ko-KR", {
    dateStyle: "medium",
    timeStyle: "medium",
  }).format(date);
}

function CheckIcon({ check }: { check: DataIntegrityCheck }) {
  if (check.status === "pass") {
    return <CheckCircle2 className="text-emerald-600" size={18} />;
  }
  if (check.status === "warning") {
    return <AlertTriangle className="text-amber-600" size={18} />;
  }
  return <ShieldAlert className="text-destructive" size={18} />;
}

function reasonLabel(reason: string) {
  switch (reason) {
    case "missing_user":
      return "사용자 없음";
    case "deleted_user":
      return "삭제된 사용자";
    case "missing_tenant":
      return "테넌트 없음";
    case "deleted_tenant":
      return "삭제된 테넌트";
    default:
      return reason;
  }
}

function recheckStatusText(status: "idle" | "running" | "success" | "error") {
  switch (status) {
    case "running":
      return "정합성 검사를 실행 중입니다.";
    case "success":
      return "검사가 완료되었습니다.";
    case "error":
      return "검사에 실패했습니다.";
    default:
      return "";
  }
}

function OrphanLoginIDTable({
  items,
  selectedIds,
  onToggle,
}: {
  items: OrphanUserLoginID[];
  selectedIds: string[];
  onToggle: (id: string) => void;
}) {
  if (items.length === 0) {
    return (
      <div className="rounded border border-border/60 px-3 py-6 text-center text-sm text-muted-foreground">
        삭제할 유령 로그인 ID가 없습니다.
      </div>
    );
  }

  const selectedSet = new Set(selectedIds);
  return (
    <div className="overflow-x-auto rounded border border-border/60">
      <table className="w-full min-w-[760px] text-sm">
        <thead className="bg-muted/50 text-left text-muted-foreground">
          <tr>
            <th className="w-12 px-3 py-2">선택</th>
            <th className="px-3 py-2">Login ID</th>
            <th className="px-3 py-2">Field</th>
            <th className="px-3 py-2">User</th>
            <th className="px-3 py-2">Tenant</th>
            <th className="px-3 py-2">사유</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-border">
          {items.map((item) => (
            <tr key={item.id}>
              <td className="px-3 py-2">
                <input
                  type="checkbox"
                  aria-label={`${item.loginId} 선택`}
                  checked={selectedSet.has(item.id)}
                  onChange={() => onToggle(item.id)}
                  className="h-4 w-4 rounded border-input"
                />
              </td>
              <td className="px-3 py-2 font-medium">{item.loginId}</td>
              <td className="px-3 py-2 text-muted-foreground">
                {item.fieldKey}
              </td>
              <td className="px-3 py-2">
                <div>{item.userEmail || "-"}</div>
                <div className="text-xs text-muted-foreground">
                  {item.userId}
                </div>
              </td>
              <td className="px-3 py-2">
                <div>{item.tenantSlug || "-"}</div>
                <div className="text-xs text-muted-foreground">
                  {item.tenantId}
                </div>
              </td>
              <td className="px-3 py-2">
                <div className="flex flex-wrap gap-1">
                  {item.reasons.map((reason) => (
                    <Badge key={reason} variant="warning">
                      {reasonLabel(reason)}
                    </Badge>
                  ))}
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function DataIntegrityContent() {
  const queryClient = useQueryClient();
  const [selectedOrphanIds, setSelectedOrphanIds] = useState<string[]>([]);
  const [recheckStatus, setRecheckStatus] = useState<
    "idle" | "running" | "success" | "error"
  >("idle");
  const { data, isLoading, isError, error, refetch, isFetching } = useQuery({
    queryKey: ["data-integrity-report"],
    queryFn: fetchDataIntegrityReport,
  });
  const orphanLoginIDsQuery = useQuery({
    queryKey: ["orphan-user-login-ids"],
    queryFn: fetchOrphanUserLoginIDs,
  });
  const deleteMutation = useMutation({
    mutationFn: deleteOrphanUserLoginIDs,
    onSuccess: async () => {
      setSelectedOrphanIds([]);
      await Promise.all([
        queryClient.invalidateQueries({ queryKey: ["data-integrity-report"] }),
        queryClient.invalidateQueries({ queryKey: ["orphan-user-login-ids"] }),
      ]);
    },
  });

  const orphanItems = orphanLoginIDsQuery.data?.items ?? [];
  const toggleOrphanID = (id: string) => {
    setSelectedOrphanIds((current) =>
      current.includes(id)
        ? current.filter((selectedID) => selectedID !== id)
        : [...current, id],
    );
  };
  const handleDeleteSelected = () => {
    if (selectedOrphanIds.length === 0) {
      return;
    }
    const confirmed = window.confirm(
      `선택한 ${selectedOrphanIds.length}개의 유령 로그인 ID를 삭제하시겠습니까?`,
    );
    if (confirmed) {
      deleteMutation.mutate(selectedOrphanIds);
    }
  };
  const isManualRechecking = recheckStatus === "running";
  const handleRecheck = async () => {
    if (isManualRechecking) {
      return;
    }
    setRecheckStatus("running");
    const result = await refetch();
    setRecheckStatus(result.isError ? "error" : "success");
  };
  const recheckMessage = recheckStatusText(recheckStatus);

  return (
    <main className="space-y-6 p-6 md:p-8">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <div>
          <p className="text-sm text-muted-foreground">System</p>
          <h2 className="text-2xl font-semibold tracking-tight">
            데이터 정합성 검증
          </h2>
        </div>
        <div className="flex flex-col items-end gap-1">
          <Button
            type="button"
            variant="outline"
            onClick={handleRecheck}
            disabled={isLoading || isFetching || isManualRechecking}
          >
            <Database size={16} />
            {isManualRechecking ? "검사 중" : "다시 검사"}
          </Button>
          {recheckMessage ? (
            <output
              aria-live="polite"
              className="text-xs text-muted-foreground"
            >
              {recheckMessage}
            </output>
          ) : null}
        </div>
      </div>

      {isError ? (
        <section className="rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-sm text-destructive">
          {(error as Error)?.message || "정합성 리포트를 불러오지 못했습니다."}
        </section>
      ) : null}

      <section className="rounded-lg border border-border bg-card p-5">
        <div className="flex flex-wrap items-center justify-between gap-3 border-b border-border pb-4">
          <div className="flex items-center gap-3">
            <div className="grid h-10 w-10 place-items-center rounded-lg bg-primary/10 text-primary">
              <ShieldAlert size={18} />
            </div>
            <div>
              <h3 className="text-base font-semibold">Read model integrity</h3>
              <p className="text-sm text-muted-foreground">
                Ory SoT를 덮어쓰지 않고 backend DB read model의 이상 징후만
                확인합니다.
              </p>
            </div>
          </div>
          {data ? (
            <Badge variant={statusBadgeVariant(data.status)}>
              {statusLabel(data.status)}
            </Badge>
          ) : null}
        </div>

        {isLoading ? (
          <div className="py-8 text-sm text-muted-foreground">불러오는 중</div>
        ) : (
          <dl className="grid gap-4 py-5 sm:grid-cols-2 lg:grid-cols-4">
            <div>
              <dt className="text-sm text-muted-foreground">검사 항목</dt>
              <dd className="mt-1 text-xl font-semibold tabular-nums">
                {data?.summary.totalChecks ?? 0}
              </dd>
            </div>
            <div>
              <dt className="text-sm text-muted-foreground">정상</dt>
              <dd className="mt-1 text-xl font-semibold tabular-nums">
                {data?.summary.passed ?? 0}
              </dd>
            </div>
            <div>
              <dt className="text-sm text-muted-foreground">실패 건수</dt>
              <dd className="mt-1 text-xl font-semibold tabular-nums">
                {data?.summary.failures ?? 0}
              </dd>
            </div>
            <div>
              <dt className="text-sm text-muted-foreground">검사 시각</dt>
              <dd className="mt-1 text-sm">
                {formatDateTime(data?.checkedAt)}
              </dd>
            </div>
          </dl>
        )}
      </section>

      <div className="space-y-4">
        {(data?.sections ?? []).map((section) => (
          <section
            key={section.key}
            className="rounded-lg border border-border bg-card p-5"
          >
            <div className="mb-4 flex items-center justify-between gap-3">
              <h3 className="text-base font-semibold">{section.label}</h3>
              <Badge variant={statusBadgeVariant(section.status)}>
                {statusLabel(section.status)}
              </Badge>
            </div>
            <div className="divide-y divide-border">
              {section.checks.map((check) => (
                <div
                  key={check.key}
                  className="grid gap-3 py-4 md:grid-cols-[1fr_auto]"
                >
                  <div className="flex gap-3">
                    <CheckIcon check={check} />
                    <div>
                      <div className="font-medium">{check.label}</div>
                      <p className="mt-1 text-sm text-muted-foreground">
                        {check.description}
                      </p>
                    </div>
                  </div>
                  <div className="flex items-center gap-3 md:justify-end">
                    <Badge variant={statusBadgeVariant(check.status)}>
                      {statusLabel(check.status)}
                    </Badge>
                    <span className="min-w-12 text-right text-lg font-semibold tabular-nums">
                      {check.count}
                    </span>
                  </div>
                </div>
              ))}
            </div>
          </section>
        ))}
      </div>

      <section className="rounded-lg border border-border bg-card p-5">
        <div className="mb-4 flex flex-wrap items-center justify-between gap-3">
          <div>
            <h3 className="text-base font-semibold">유령 로그인 ID 정리</h3>
            <p className="mt-1 text-sm text-muted-foreground">
              삭제되었거나 존재하지 않는 사용자/테넌트를 참조하는 로그인 ID를
              확인한 뒤 선택 삭제합니다.
            </p>
          </div>
          <Button
            type="button"
            variant="destructive"
            onClick={handleDeleteSelected}
            disabled={
              selectedOrphanIds.length === 0 || deleteMutation.isPending
            }
          >
            선택 삭제
          </Button>
        </div>
        {orphanLoginIDsQuery.isError ? (
          <div className="mb-3 rounded border border-destructive/30 bg-destructive/10 p-3 text-sm text-destructive">
            유령 로그인 ID 대상을 불러오지 못했습니다.
          </div>
        ) : null}
        {deleteMutation.data ? (
          <div className="mb-3 rounded border border-emerald-200 bg-emerald-50 p-3 text-sm text-emerald-800 dark:border-emerald-900 dark:bg-emerald-950/40 dark:text-emerald-200">
            {deleteMutation.data.deletedCount}개의 유령 로그인 ID를
            삭제했습니다.
          </div>
        ) : null}
        <OrphanLoginIDTable
          items={orphanItems}
          selectedIds={selectedOrphanIds}
          onToggle={toggleOrphanID}
        />
      </section>
    </main>
  );
}

export default function DataIntegrityPage() {
  return (
    <RoleGuard
      roles={["super_admin"]}
      fallback={
        <main className="p-6 md:p-8">
          <section className="rounded-lg border border-border bg-card p-5">
            <h2 className="text-lg font-semibold">접근 권한이 없습니다</h2>
            <p className="mt-2 text-sm text-muted-foreground">
              이 화면은 super_admin 권한으로만 접근할 수 있습니다.
            </p>
          </section>
        </main>
      }
    >
      <DataIntegrityContent />
    </RoleGuard>
  );
}
