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,
  deleteOrphanUserLoginIDs,
  fetchDataIntegrityReport,
  fetchOrphanUserLoginIDs,
  type OrphanUserLoginID,
} from "../../lib/adminApi";
import { t } from "../../lib/i18n";
import { getAdminDateLocale } from "../../lib/locale";
import { UserProjectionContent } from "../projections/UserProjectionPage";

function statusLabel(status: DataIntegrityStatus) {
  switch (status) {
    case "pass":
      return t("ui.admin.integrity.status.pass", "정상");
    case "warning":
      return t("ui.admin.integrity.status.warning", "주의");
    case "fail":
      return t("ui.admin.integrity.status.fail", "실패");
    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(getAdminDateLocale(), {
    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 t("ui.admin.integrity.reason.missing_user", "사용자 없음");
    case "deleted_user":
      return t("ui.admin.integrity.reason.deleted_user", "삭제된 사용자");
    case "missing_tenant":
      return t("ui.admin.integrity.reason.missing_tenant", "테넌트 없음");
    case "deleted_tenant":
      return t("ui.admin.integrity.reason.deleted_tenant", "삭제된 테넌트");
    default:
      return reason;
  }
}

function integritySectionLabel(key: string, fallback: string) {
  switch (key) {
    case "tenant_integrity":
      return t("ui.admin.integrity.section.tenant_integrity", fallback);
    case "user_integrity":
      return t("ui.admin.integrity.section.user_integrity", fallback);
    default:
      return fallback;
  }
}

function integritySectionDescription(key: string) {
  switch (key) {
    case "tenant_integrity":
      return t(
        "msg.admin.integrity.section.tenant_integrity.description",
        "테넌트 slug 중복과 부모 관계 이상을 확인합니다.",
      );
    case "user_integrity":
      return t(
        "msg.admin.integrity.section.user_integrity.description",
        "사용자와 로그인 ID 참조의 고아 레코드를 확인합니다.",
      );
    default:
      return "";
  }
}

function integrityCheckLabel(key: string, fallback: string) {
  switch (key) {
    case "duplicate_tenant_slugs":
      return t(
        "ui.admin.integrity.check.duplicate_tenant_slugs.title",
        fallback,
      );
    case "orphan_tenant_parents":
      return t(
        "ui.admin.integrity.check.orphan_tenant_parents.title",
        fallback,
      );
    case "orphan_user_tenant_memberships":
      return t(
        "ui.admin.integrity.check.orphan_user_tenant_memberships.title",
        fallback,
      );
    case "orphan_user_login_id_tenants":
      return t(
        "ui.admin.integrity.check.orphan_user_login_id_tenants.title",
        fallback,
      );
    case "orphan_user_login_id_users":
      return t(
        "ui.admin.integrity.check.orphan_user_login_id_users.title",
        fallback,
      );
    default:
      return fallback;
  }
}

function integrityCheckDescription(key: string, fallback: string) {
  switch (key) {
    case "duplicate_tenant_slugs":
      return t(
        "msg.admin.integrity.check.duplicate_tenant_slugs.description",
        fallback,
      );
    case "orphan_tenant_parents":
      return t(
        "msg.admin.integrity.check.orphan_tenant_parents.description",
        fallback,
      );
    case "orphan_user_tenant_memberships":
      return t(
        "msg.admin.integrity.check.orphan_user_tenant_memberships.description",
        fallback,
      );
    case "orphan_user_login_id_tenants":
      return t(
        "msg.admin.integrity.check.orphan_user_login_id_tenants.description",
        fallback,
      );
    case "orphan_user_login_id_users":
      return t(
        "msg.admin.integrity.check.orphan_user_login_id_users.description",
        fallback,
      );
    default:
      return fallback;
  }
}

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

function pageTabClassName(active: boolean) {
  return `relative px-6 py-3 text-sm font-medium transition-colors ${
    active
      ? "border-b-2 border-primary text-primary"
      : "text-muted-foreground hover:text-foreground"
  }`;
}

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">
        {t(
          "msg.admin.integrity.orphan_login_ids.empty",
          "삭제할 유령 로그인 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">
              {t("ui.admin.integrity.table.select", "선택")}
            </th>
            <th className="px-3 py-2">
              {t("ui.admin.integrity.table.login_id", "Login ID")}
            </th>
            <th className="px-3 py-2">
              {t("ui.admin.integrity.table.field", "Field")}
            </th>
            <th className="px-3 py-2">
              {t("ui.admin.integrity.table.user", "User")}
            </th>
            <th className="px-3 py-2">
              {t("ui.admin.integrity.table.tenant", "Tenant")}
            </th>
            <th className="px-3 py-2">
              {t("ui.admin.integrity.table.reason", "사유")}
            </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={t(
                    "ui.admin.integrity.table.select_item",
                    "{{loginId}} 선택",
                    { loginId: 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 [activeTab, setActiveTab] = useState<"integrity" | "projection">(
    "integrity",
  );
  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(
      t(
        "msg.admin.integrity.orphan_login_ids.delete_confirm",
        "선택한 {{count}}개의 유령 로그인 ID를 삭제하시겠습니까?",
        { count: selectedOrphanIds.length },
      ),
    );
    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">
      <header className="flex flex-shrink-0 flex-wrap items-start justify-between gap-4 sticky top-[-2.5rem] z-20 -mt-4 bg-background/95 pb-2 pt-4 backdrop-blur">
        <div className="flex min-w-0 items-start gap-3">
          <div className="mt-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-primary/15 bg-primary/10 text-primary">
            <Database size={20} />
          </div>
          <div className="space-y-2">
            <h2 className="text-3xl font-semibold">
              {t("ui.admin.integrity.title", "데이터 정합성 검증")}
            </h2>
            <p className="text-sm text-muted-foreground">
              {t(
                "msg.admin.integrity.subtitle",
                "Review integrity status and inspect checks across the admin data model.",
              )}
            </p>
          </div>
        </div>
        {activeTab === "integrity" ? (
          <div className="flex flex-col items-end gap-1">
            <Button
              type="button"
              variant="outline"
              onClick={handleRecheck}
              disabled={isLoading || isFetching || isManualRechecking}
            >
              <Database size={16} />
              {isManualRechecking
                ? t("ui.admin.integrity.recheck.running", "검사 중")
                : t("ui.admin.integrity.recheck.run", "다시 검사")}
            </Button>
            {recheckMessage ? (
              <output
                aria-live="polite"
                className="text-xs text-muted-foreground"
              >
                {recheckMessage}
              </output>
            ) : null}
          </div>
        ) : null}
      </header>

      <div
        className="flex border-b border-border"
        role="tablist"
        aria-label="데이터 정합성 탭"
      >
        <button
          type="button"
          role="tab"
          aria-selected={activeTab === "integrity"}
          className={pageTabClassName(activeTab === "integrity")}
          onClick={() => setActiveTab("integrity")}
        >
          {t("ui.admin.integrity.tab_checks", "정합성 검사")}
        </button>
        <button
          type="button"
          role="tab"
          aria-selected={activeTab === "projection"}
          className={pageTabClassName(activeTab === "projection")}
          onClick={() => setActiveTab("projection")}
        >
          {t("ui.admin.integrity.tab_user_projection", "사용자 동기화")}
        </button>
      </div>

      {activeTab === "integrity" ? (
        <div className="space-y-4 pb-6 animate-in fade-in duration-500">
          {isError ? (
            <section className="rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-sm text-destructive">
              {(error as Error)?.message ||
                t(
                  "msg.admin.integrity.report.load_error",
                  "정합성 리포트를 불러오지 못했습니다.",
                )}
            </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>
                <h3 className="text-lg font-bold flex items-center gap-2">
                  {t(
                    "ui.admin.integrity.read_model.title",
                    "Read model integrity",
                  )}
                </h3>
                <p className="text-sm text-muted-foreground">
                  {t(
                    "msg.admin.integrity.read_model.description",
                    "Ory SoT를 덮어쓰지 않고 backend DB read model의 이상 징후만 확인합니다.",
                  )}
                </p>
              </div>
              {data ? (
                <Badge variant={statusBadgeVariant(data.status)}>
                  {statusLabel(data.status)}
                </Badge>
              ) : null}
            </div>

            {isLoading ? (
              <div className="py-8 text-sm text-muted-foreground">
                {t("ui.admin.integrity.loading", "불러오는 중")}
              </div>
            ) : (
              <dl className="grid gap-4 py-5 sm:grid-cols-2 lg:grid-cols-4">
                <div>
                  <dt className="text-sm text-muted-foreground">
                    {t("ui.admin.integrity.summary.total_checks", "검사 항목")}
                  </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">
                    {t("ui.admin.integrity.summary.passed", "정상")}
                  </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">
                    {t("ui.admin.integrity.summary.failures", "실패 건수")}
                  </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">
                    {t("ui.admin.integrity.summary.checked_at", "검사 시각")}
                  </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">
                  <div className="space-y-1">
                    <h3 className="text-lg font-bold flex items-center gap-2">
                      {integritySectionLabel(section.key, section.label)}
                    </h3>
                    <p className="text-sm text-muted-foreground">
                      {integritySectionDescription(section.key)}
                    </p>
                  </div>
                  <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">
                            {integrityCheckLabel(check.key, check.label)}
                          </div>
                          <p className="mt-1 text-sm text-muted-foreground">
                            {integrityCheckDescription(
                              check.key,
                              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-lg font-bold flex items-center gap-2">
                  {t(
                    "ui.admin.integrity.orphan_login_ids.title",
                    "유령 로그인 ID 정리",
                  )}
                </h3>
                <p className="mt-1 text-sm text-muted-foreground">
                  {t(
                    "msg.admin.integrity.orphan_login_ids.description",
                    "삭제되었거나 존재하지 않는 사용자/테넌트를 참조하는 로그인 ID를 확인한 뒤 선택 삭제합니다.",
                  )}
                </p>
              </div>
              <Button
                type="button"
                variant="destructive"
                onClick={handleDeleteSelected}
                disabled={
                  selectedOrphanIds.length === 0 || deleteMutation.isPending
                }
              >
                {t("ui.admin.integrity.orphan_login_ids.delete", "선택 삭제")}
              </Button>
            </div>
            {orphanLoginIDsQuery.isError ? (
              <div className="mb-3 rounded border border-destructive/30 bg-destructive/10 p-3 text-sm text-destructive">
                {t(
                  "msg.admin.integrity.orphan_login_ids.load_error",
                  "유령 로그인 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">
                {t(
                  "msg.admin.integrity.orphan_login_ids.delete_success",
                  "{{count}}개의 유령 로그인 ID를 삭제했습니다.",
                  { count: deleteMutation.data.deletedCount },
                )}
              </div>
            ) : null}
            <OrphanLoginIDTable
              items={orphanItems}
              selectedIds={selectedOrphanIds}
              onToggle={toggleOrphanID}
            />
          </section>
        </div>
      ) : (
        <div className="animate-in fade-in duration-500">
          <UserProjectionContent embedded />
        </div>
      )}
    </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">
              {t("ui.admin.integrity.forbidden.title", "접근 권한이 없습니다")}
            </h2>
            <p className="mt-2 text-sm text-muted-foreground">
              {t(
                "msg.admin.integrity.forbidden.description",
                "이 화면은 super_admin 권한으로만 접근할 수 있습니다.",
              )}
            </p>
          </section>
        </main>
      }
    >
      <DataIntegrityContent />
    </RoleGuard>
  );
}
