import { useCallback, useEffect, useState } from "react";
import { useOutletContext } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { useAuth } from "@/contexts/AuthContext";
import {
  deleteApplicationEvidence,
  getApplicationEvidence,
  patchEvidenceReview,
  uploadApplicationEvidence,
  type EvidenceItemMeta,
  type ServerEvidenceKind,
} from "@/lib/applicationEvidenceApi";
import { ApplicationEvidenceDashboard } from "./ApplicationEvidenceDashboard";
import { ApplicationEvidenceViewerPanel } from "./ApplicationEvidenceViewerPanel";
import type { ApplicationEvidenceOutletContext } from "./ApplicationEvidenceLayout";
import { EVIDENCE_KIND_ROWS } from "./applicationEvidenceConstants";
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import { apiClient, detailFromApiError } from "@/shared/api/client";
import type { ApplicationItem } from "@/data/mockApplications";
import { axiosSuccessStatusOnly, getNestedData } from "@/lib/applicationReviewApi";
import { cn } from "@/lib/utils";
import { markEvidenceStaffReviewAcknowledged } from "@/components/evidence/evidenceStaffReviewAck";

type ApiLikeError = { status?: number; message?: string; data?: { detail?: string | { msg?: string }[] } };

function parseEvidenceAccessError(
  err: unknown,
): { title: string; description: string; alertVariant: "default" | "destructive"; alertClassName?: string } {
  const e = err as ApiLikeError;
  const st = e.status;
  let detail = "";
  const d = e.data?.detail;
  if (typeof d === "string") {
    detail = d;
  } else if (Array.isArray(d)) {
    detail = d
      .map((x) => (typeof x === "object" && x && "msg" in x ? String((x as { msg: string }).msg) : String(x)))
      .join(" ");
  } else {
    detail = e.message || "";
  }
  const accessStyle =
    "border-amber-500/50 bg-amber-50/60 text-foreground dark:border-amber-500/35 dark:bg-amber-950/30 [&_h5]:text-foreground";
  if (st === 401) {
    return {
      title: "Cần đăng nhập",
      description: detail || "Phiên đã hết hạn. Đăng nhập lại rồi mở lại trang minh chứng.",
      alertVariant: "default",
      alertClassName: accessStyle,
    };
  }
  if (st === 403) {
    return {
      title: "Không có quyền với mã hồ sơ này",
      description:
        detail ||
        "Máy chủ từ chối: tài khoản hiện tại không phải chủ sở hữu sáng kiến tương ứng mã case trong URL, hoặc bạn mở nhầm liên kết. Hãy vào Lịch sử đăng ký (Tài liệu) và mở kho minh chứng từ đúng dòng hồ sơ — mã `draftCaseId` phải trùng với sáng kiến của bạn trên máy chủ.",
      alertVariant: "default",
      alertClassName: accessStyle,
    };
  }
  if (st === 503) {
    return {
      title: "Máy chủ hoặc cơ sở dữ liệu chưa sẵn sàng",
      description:
        detail ||
        "Có thể cơ sở dữ liệu chưa áp dụng migration mới (cột `storage_kind` trên `application_artifacts`). Hãy khởi động lại `be0` để chạy `scripts/apply_initiative_migrations.py`, hoặc chạy thủ công `be0/migrations/009_backup_artifact_roles_storage_kind.sql` rồi tải lại trang.",
      alertVariant: "destructive",
    };
  }
  return {
    title: "Không tải được dữ liệu minh chứng",
    description: detail || (err instanceof Error ? err.message : "Lỗi mạng hoặc máy chủ (≥500)."),
    alertVariant: "destructive",
  };
}

/**
 * Thân tab « Quản lý »: tải / xóa (ứng viên) hoặc duyệt / từ chối (quản trị, hội đồng).
 */
export function ApplicationEvidenceManagePage() {
  const { caseId, applicationId } = useOutletContext<ApplicationEvidenceOutletContext>();
  const { hasRole, hasPermission } = useAuth();
  const isStaff = hasRole("admin") || hasRole("editor");
  const isApplicant = hasRole("viewer");
  const canEditOwn = isApplicant && hasPermission("application.edit");
  const [viewer, setViewer] = useState<{ kind: ServerEvidenceKind; meta: EvidenceItemMeta } | null>(null);

  const openViewer = (kind: ServerEvidenceKind, meta: EvidenceItemMeta) => {
    setViewer({ kind, meta });
  };
  const closeViewer = () => setViewer(null);

  const detailQuery = useQuery({
    queryKey: ["application-item", applicationId],
    enabled: Boolean(applicationId),
    queryFn: async (): Promise<ApplicationItem | null> => {
      const raw = await apiClient.get(
        `/api/applications/${encodeURIComponent(applicationId!)}`,
        axiosSuccessStatusOnly,
      );
      const d = getNestedData<ApplicationItem | null>(raw);
      return d;
    },
  });

  const evidenceQuery = useQuery({
    queryKey: ["evidence", caseId],
    queryFn: () => getApplicationEvidence(caseId),
  });

  /** Presigned URLs rotate on each GET; keeping a stale snapshot after upload/refetch yields a blank iframe. */
  useEffect(() => {
    const data = evidenceQuery.data;
    if (!data) return;
    setViewer((prev) => {
      if (!prev) return prev;
      const fresh = data[prev.kind];
      if (!fresh) return null;
      return prev.meta === fresh ? prev : { kind: prev.kind, meta: fresh };
    });
  }, [evidenceQuery.data]);

  const refetch = useCallback(() => {
    void evidenceQuery.refetch();
  }, [evidenceQuery]);

  const onUpload = async (kind: ServerEvidenceKind, file: File) => {
    try {
      await uploadApplicationEvidence(caseId, kind, file);
      toast.success("Đã tải lên minh chứng.");
      refetch();
    } catch (e: unknown) {
      toast.error(detailFromApiError(e, "Tải lên thất bại."));
    }
  };

  const onDelete = async (kind: ServerEvidenceKind) => {
    if (!window.confirm("Xóa tệp minh chứng này?")) return;
    try {
      await deleteApplicationEvidence(caseId, kind);
      toast.success("Đã xóa minh chứng.");
      if (viewer?.kind === kind) closeViewer();
      refetch();
    } catch (e: unknown) {
      toast.error(detailFromApiError(e, "Không xóa được."));
    }
  };

  const onReview = async (kind: ServerEvidenceKind, decision: "approved" | "rejected") => {
    try {
      await patchEvidenceReview(caseId, kind, decision);
      markEvidenceStaffReviewAcknowledged(caseId);
      toast.success(decision === "approved" ? "Đã phê duyệt minh chứng." : "Đã từ chối minh chứng.");
      refetch();
    } catch (e: unknown) {
      toast.error(detailFromApiError(e, "Cập nhật thất bại."));
    }
  };

  if (evidenceQuery.isLoading) {
    return (
      <div className="flex items-center gap-2 text-muted-foreground py-8">
        <Loader2 className="h-5 w-5 animate-spin" />
        Đang tải kho minh chứng…
      </div>
    );
  }

  if (evidenceQuery.isError) {
    const { title, description, alertVariant, alertClassName } = parseEvidenceAccessError(evidenceQuery.error);
    return (
      <Alert role="alert" variant={alertVariant} className={cn(alertClassName)}>
        <AlertTitle>{title}</AlertTitle>
        <AlertDescription className="whitespace-pre-line text-inherit opacity-90">{description}</AlertDescription>
      </Alert>
    );
  }

  const bundle = evidenceQuery.data!;
  const viewerKindLabel = viewer
    ? (EVIDENCE_KIND_ROWS.find((x) => x.key === viewer.kind)?.title ?? viewer.kind)
    : "";

  return (
    <div className="w-full min-w-0 space-y-4">
      <ResizablePanelGroup
        key={caseId}
        direction="horizontal"
        className={cn("w-full min-w-0 max-w-full min-h-[min(85vh,920px)] rounded-md border")}
      >
        <ResizablePanel id="evidence-dashboard" order={1} defaultSize={viewer ? 52 : 100} minSize={viewer ? 32 : 100} className="min-w-0">
          <ApplicationEvidenceDashboard
            applicationId={applicationId}
            applicationDetailQuery={detailQuery}
            bundle={bundle}
            isStaff={isStaff}
            canEditOwn={canEditOwn}
            onOpenViewer={openViewer}
            onUpload={onUpload}
            onDelete={onDelete}
            onReview={onReview}
          />
        </ResizablePanel>
        {viewer ? (
          <>
            <ResizableHandle withHandle />
            <ResizablePanel id="evidence-viewer" order={2} defaultSize={48} minSize={28} className="min-w-0">
              <ApplicationEvidenceViewerPanel
                caseId={caseId}
                kind={viewer.kind}
                kindLabel={viewerKindLabel}
                meta={viewer.meta}
                onClose={closeViewer}
              />
            </ResizablePanel>
          </>
        ) : null}
      </ResizablePanelGroup>
    </div>
  );
}
