import { useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import {
  Alert,
  Badge,
  Box,
  Button,
  FileButton,
  Group,
  Loader,
  Paper,
  Progress,
  Stack,
  Text,
  Textarea,
  ThemeIcon,
  Tooltip,
} from "@mantine/core";
import {
  AlertCircle,
  CheckCircle2,
  Clock,
  Download,
  Eye,
  FileCheck2,
  FileText,
  MessageSquareWarning,
  Upload,
  UserCheck,
} from "lucide-react";
import type { Freight } from "@edr/types";
import { isViewable } from "@edr/ui-common";

import { SectionCard } from "@/components/bookings/detail/SectionCard";
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import { contractsService } from "@/services/contracts.service";
import {
  downloadBookingFile,
  fetchViewableFile,
} from "@/services/files.service";
import { useContractClearanceMutations } from "@/hooks/contracts/useContracts";
import { useFileViewer } from "@/hooks/useFileViewer";

export interface ContractClearanceReviewSectionProps {
  contractId: string;
  /** Called after any review/finalize mutation so the parent can refetch. */
  onChanged?: () => void;
  /** Hide the inline progress summary (e.g. when the parent renders its own). */
  hideSummary?: boolean;
  /**
   * Path A (non-customs): the reviewer is Operations, not GL, and there is no GL
   * output upload step. Routes review/finalize to the Operations endpoints.
   */
  selfClear?: boolean;
  /**
   * Clearance is finalized — render the document outcomes (approved / queried,
   * by whom, when) but hide all approve / query / finalize actions.
   */
  readOnly?: boolean;
  /**
   * Document approvals are locked (e.g. after all docs approved in phased flow)
   * but queries remain available until {@link queriesLocked} or {@link readOnly}.
   */
  approvalsLocked?: boolean;
  /**
   * Pre-clearance finalized — block opening new queries on customer documents.
   */
  queriesLocked?: boolean;
  /**
   * ONE_TIME customs contracts use the phased milestone workflow. Hides the
   * legacy "Finalize document approval" shortcut; booking readiness follows delivery
   * order (import) or export release.
   */
  phasedCustoms?: boolean;
}

const STATUS_META: Record<
  Freight.ContractDocReviewStatus,
  { label: string; color: string }
> = {
  APPROVED: { label: "Approved", color: "edr-green" },
  QUERIED: { label: "Queried", color: "red" },
  PENDING: { label: "Pending", color: "gray" },
};

function formatReviewedAt(value?: string | null): string | null {
  if (!value) return null;
  const d = new Date(value);
  if (Number.isNaN(d.getTime())) return null;
  return d.toLocaleString(undefined, {
    month: "short",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

/**
 * Pre-booking clearance review for a CONTRACT. Approve / query each customer
 * document, upload GL output documents, and finalize once every required
 * document is approved. When `readOnly` it becomes an audit view: approved /
 * queried outcomes with reviewer + timestamp, no actions.
 */
export function ContractClearanceReviewSection({
  contractId,
  onChanged,
  hideSummary,
  selfClear = false,
  readOnly = false,
  phasedCustoms = false,
  approvalsLocked = false,
  queriesLocked = false,
}: ContractClearanceReviewSectionProps) {
  const [queryNotes, setQueryNotes] = useState<Record<string, string>>({});
  const [openQuery, setOpenQuery] = useState<Record<string, boolean>>({});
  const [uploadingKey, setUploadingKey] = useState<string | null>(null);
  const { view, viewer } = useFileViewer();

  const reviewerTeam = selfClear ? "Operations" : "Global Logistics";

  const { data: clearance, isLoading } = useQuery({
    queryKey: QUERY_KEYS.CONTRACTS.clearance(contractId),
    queryFn: () => contractsService.getClearance(contractId),
  });

  const { reviewDocument, approveAll, uploadOutputDocuments, finalizeClearance } =
    useContractClearanceMutations(contractId, selfClear);

  const customerDocs = useMemo(
    () =>
      (clearance?.documents ?? []).filter((d) => d.uploadedBy === "customer"),
    [clearance],
  );
  // GL output documents — anything not uploaded by the customer. The backend
  // tags these `uploadedBy: 'gl'`; matching on "not customer" keeps it robust if
  // that ever splits into gl_et / gl_dj.
  const glDocs = useMemo(
    () =>
      (clearance?.documents ?? []).filter((d) => d.uploadedBy !== "customer"),
    [clearance],
  );

  const stats = useMemo(() => {
    const total = customerDocs.length;
    const approved = customerDocs.filter(
      (d) => d.reviewStatus === "APPROVED",
    ).length;
    const queried = customerDocs.filter(
      (d) => d.reviewStatus === "QUERIED",
    ).length;
    const pending = total - approved - queried;
    const pct = total === 0 ? 0 : Math.round((approved / total) * 100);
    return { total, approved, queried, pending, pct };
  }, [customerDocs]);

  // Documents with a file uploaded but not yet approved — "Approve all" targets.
  const approvableKeys = customerDocs
    .filter((d) => d.file && d.reviewStatus !== "APPROVED")
    .map((d) => d.fileKey);

  const hasDocsAwaitingApproval = customerDocs.some(
    (d) => d.file && d.reviewStatus !== "APPROVED",
  );
  const effectiveApprovalsLocked = approvalsLocked && !hasDocsAwaitingApproval;

  if (isLoading || !clearance) {
    return (
      <Group justify="center" py="xl" gap={10}>
        <Loader size="sm" color="edr-green" />
        <Text c="dimmed">Loading clearance…</Text>
      </Group>
    );
  }

  const handleReview = (
    fileKey: string,
    status: "APPROVED" | "QUERIED",
    note?: string,
  ) =>
    reviewDocument.mutate(
      { fileKey, status, note },
      {
        onSuccess: () => {
          if (status === "QUERIED")
            setOpenQuery((o) => ({ ...o, [fileKey]: false }));
          onChanged?.();
        },
      },
    );

  return (
    <Stack gap="lg">
      <SectionCard
        icon={FileText}
        title="Customer documents"
        subtitle={
          readOnly
            ? `Reviewed by the ${reviewerTeam} team.`
            : effectiveApprovalsLocked
              ? "Documents are approved — you can still open a query if something needs fixing."
              : "Approve each document, or open a query to tell the customer what to fix."
        }
        extra={
          <Group gap={10} wrap="nowrap" align="center">
            <Text size="xs" c="dimmed" fw={600}>
              {stats.approved}/{stats.total} approved
            </Text>
            {!readOnly && !effectiveApprovalsLocked && approvableKeys.length > 0 && (
              <Button
                size="compact-sm"
                color="edr-green"
                radius="md"
                leftSection={<FileCheck2 size={14} />}
                loading={approveAll.isPending}
                disabled={reviewDocument.isPending}
                onClick={() => approveAll.mutate(approvableKeys)}
              >
                Approve all ({approvableKeys.length})
              </Button>
            )}
          </Group>
        }
      >
        <Stack gap={12}>
          {!hideSummary && stats.total > 0 && (
            <Box>
              <Progress
                value={stats.pct}
                color="edr-green"
                radius="xl"
                size="sm"
                mb={6}
              />
              <Group gap="lg">
                <StatPill color="edr-green" label="Approved" value={stats.approved} />
                <StatPill color="red" label="Queried" value={stats.queried} />
                <StatPill color="gray" label="Pending" value={stats.pending} />
              </Group>
            </Box>
          )}
          {customerDocs.length === 0 ? (
            <Text size="sm" c="dimmed">
              No customer documents are required for this contract.
            </Text>
          ) : (
            customerDocs.map((doc) => (
              <DocReviewCard
                key={`${doc.settingCode}:${doc.fileKey}`}
                doc={doc}
                reviewerTeam={reviewerTeam}
                readOnly={readOnly}
                approvalsLocked={effectiveApprovalsLocked}
                queriesLocked={queriesLocked}
                note={queryNotes[doc.fileKey] ?? ""}
                queryOpen={openQuery[doc.fileKey] ?? false}
                onToggleQuery={(open) =>
                  setOpenQuery((o) => ({ ...o, [doc.fileKey]: open }))
                }
                onNote={(v) =>
                  setQueryNotes((n) => ({ ...n, [doc.fileKey]: v }))
                }
                onApprove={() => handleReview(doc.fileKey, "APPROVED")}
                onQuery={() =>
                  handleReview(doc.fileKey, "QUERIED", queryNotes[doc.fileKey])
                }
                onView={view}
                busy={reviewDocument.isPending}
              />
            ))
          )}
        </Stack>
      </SectionCard>

      {glDocs.length > 0 && !phasedCustoms && (
        <SectionCard
          icon={Upload}
          title="GL output documents"
          subtitle="Upload each document individually — changes save immediately."
          accent="edr-green"
        >
          <Stack gap={10}>
            {glDocs.map((doc) => {
              const isUploading =
                uploadingKey === doc.fileKey && uploadOutputDocuments.isPending;
              return (
                <Group key={doc.fileKey} justify="space-between" wrap="nowrap">
                  <Group gap={8} wrap="nowrap" style={{ minWidth: 0 }}>
                    <FileText size={16} color="var(--mantine-color-edr-green-6)" />
                    <Text fz="13px" c="edr-text" truncate>
                      {doc.label}
                      {doc.required ? " *" : ""}
                    </Text>
                  </Group>
                  <Group gap={8} wrap="nowrap">
                    {doc.file ? (
                      <>
                        {isViewable({
                          name: doc.file.name,
                          url: "",
                        }) && (
                          <Tooltip label="View">
                            <Box
                              component="button"
                              type="button"
                              onClick={() =>
                                void fetchViewableFile(
                                  doc.file!.id,
                                  doc.file!.name,
                                ).then(view)
                              }
                              c="edr-green"
                              style={{
                                display: "flex",
                                background: "transparent",
                                border: "none",
                                cursor: "pointer",
                              }}
                            >
                              <Eye size={15} />
                            </Box>
                          </Tooltip>
                        )}
                        <Tooltip label="Download">
                          <Box
                            component="button"
                            type="button"
                            onClick={() =>
                              void downloadBookingFile(
                                doc.file!.id,
                                doc.file!.name,
                              )
                            }
                            c="edr-green"
                            style={{
                              display: "flex",
                              background: "transparent",
                              border: "none",
                              cursor: "pointer",
                            }}
                          >
                            <Download size={15} />
                          </Box>
                        </Tooltip>
                      </>
                    ) : (
                      <Text fz="12px" c="edr-muted">
                        Not uploaded
                      </Text>
                    )}
                    {!readOnly && (
                      <FileButton
                        onChange={(f) => {
                          if (!f) return;
                          setUploadingKey(doc.fileKey);
                          uploadOutputDocuments.mutate(
                            { [doc.fileKey]: f },
                            { onSuccess: () => { setUploadingKey(null); onChanged?.(); },
                              onError: () => setUploadingKey(null) },
                          );
                        }}
                        accept="application/pdf,image/*"
                        disabled={isUploading}
                      >
                        {(props) => (
                          <Button
                            {...props}
                            size="compact-xs"
                            variant="light"
                            color="edr-green"
                            leftSection={
                              isUploading ? (
                                <Loader size={12} color="edr-green" />
                              ) : (
                                <Upload size={13} />
                              )
                            }
                            loading={isUploading}
                          >
                            {doc.file ? "Replace" : "Upload"}
                          </Button>
                        )}
                      </FileButton>
                    )}
                  </Group>
                </Group>
              );
            })}
          </Stack>
        </SectionCard>
      )}

      {!readOnly && finalizeClearance.isError && (
        <Alert color="red" radius="md" icon={<AlertCircle size={16} />}>
          {finalizeClearance.error instanceof Error
            ? finalizeClearance.error.message
            : "Could not finalize document approval."}
        </Alert>
      )}

      {readOnly ? (
        <Paper
          withBorder
          radius="md"
          p="md"
          style={{
            borderColor: "var(--mantine-color-edr-green-3)",
            background:
              "linear-gradient(135deg, var(--mantine-color-edr-green-0) 0%, #FFFFFF 70%)",
          }}
        >
          <Group gap={10} wrap="nowrap">
            <ThemeIcon variant="light" color="edr-green" radius="md" size={28}>
              <CheckCircle2 size={15} />
            </ThemeIcon>
            <Text fz="12.5px" c="dimmed">
              {phasedCustoms
                ? "Document review is complete. Continue customs milestones in the action panel."
                : `Clearance was finalized by the ${reviewerTeam} team. This is a read-only record of the approved documents.`}
            </Text>
          </Group>
        </Paper>
      ) : phasedCustoms && effectiveApprovalsLocked ? (
        <Paper withBorder radius="md" p="md">
          <Group gap={8} wrap="nowrap" style={{ minWidth: 0 }}>
            <ThemeIcon variant="light" color="edr-green" radius="md" size={28}>
              <CheckCircle2 size={15} />
            </ThemeIcon>
            <Text fz="12.5px" c="dimmed">
              Document review is complete. Use the action panel for declaration, duty, and
              transit steps
              {queriesLocked
                ? ". Pre-clearance is finalized — customer documents can no longer be queried."
                : " — or open a query above if a customer document needs correction."}
            </Text>
          </Group>
        </Paper>
      ) : phasedCustoms ? (
        <Paper withBorder radius="md" p="md">
          <Group gap={8} wrap="nowrap" style={{ minWidth: 0 }}>
            <ThemeIcon
              variant="light"
              color={clearance.allApproved ? "edr-green" : "gray"}
              radius="md"
              size={28}
            >
              <FileCheck2 size={15} />
            </ThemeIcon>
            <Text fz="12.5px" c="dimmed">
              {clearance.allApproved
                ? "All required documents are approved. Continue declaration, duty, and transit in the action panel."
                : "Approve every required document to unlock the customs milestone steps."}
            </Text>
          </Group>
        </Paper>
      ) : (
        <Paper withBorder radius="md" p="md">
          <Group justify="space-between" wrap="nowrap">
            <Group gap={8} wrap="nowrap" style={{ minWidth: 0 }}>
              <ThemeIcon
                variant="light"
                color={clearance.allApproved ? "edr-green" : "gray"}
                radius="md"
                size={28}
              >
                <FileCheck2 size={15} />
              </ThemeIcon>
              <Text fz="12.5px" c="dimmed">
                {clearance.allApproved
                  ? "All required documents are approved — you can finalize."
                  : "Approve every required document to unlock finalization."}
              </Text>
            </Group>
            <Button
              color="edr-green"
              radius="md"
              leftSection={<CheckCircle2 size={16} />}
              disabled={!clearance.allApproved}
              loading={finalizeClearance.isPending}
              onClick={() =>
                finalizeClearance.mutate(undefined, {
                  onSuccess: () => onChanged?.(),
                })
              }
            >
              Finalize document approval
            </Button>
          </Group>
        </Paper>
      )}
      {viewer}
    </Stack>
  );
}

function StatPill({
  color,
  label,
  value,
}: {
  color: string;
  label: string;
  value: number;
}) {
  return (
    <Group gap={6} wrap="nowrap">
      <Box
        style={{
          width: 8,
          height: 8,
          borderRadius: 999,
          background: `var(--mantine-color-${color}-6)`,
        }}
      />
      <Text fz="12.5px" c="edr-text" fw={600}>
        {value}
      </Text>
      <Text fz="12.5px" c="dimmed">
        {label}
      </Text>
    </Group>
  );
}

function DocReviewCard({
  doc,
  reviewerTeam,
  readOnly,
  approvalsLocked,
  queriesLocked,
  note,
  queryOpen,
  onToggleQuery,
  onNote,
  onApprove,
  onQuery,
  onView,
  busy,
}: {
  doc: Freight.ContractClearanceDocument;
  reviewerTeam: string;
  readOnly: boolean;
  approvalsLocked: boolean;
  queriesLocked: boolean;
  note: string;
  queryOpen: boolean;
  onToggleQuery: (open: boolean) => void;
  onNote: (v: string) => void;
  onApprove: () => void;
  onQuery: () => void;
  onView: (file: { name: string; url: string }) => void;
  busy: boolean;
}) {
  const status = doc.reviewStatus ?? "PENDING";
  const meta = STATUS_META[status];
  const hasFile = !!doc.file;
  const isApproved = status === "APPROVED";
  const isQueried = status === "QUERIED";
  const reviewedAt = formatReviewedAt(doc.reviewedAt);

  // Approved cards get a light green gradient + green border so the outcome is
  // instantly scannable; queried cards get a soft red; pending stay neutral.
  const cardStyle = isApproved
    ? {
        borderColor: "var(--mantine-color-edr-green-3)",
        background:
          "linear-gradient(135deg, var(--mantine-color-edr-green-0) 0%, #FFFFFF 72%)",
      }
    : isQueried
      ? {
          borderColor: "var(--mantine-color-red-2)",
          background:
            "linear-gradient(135deg, var(--mantine-color-red-0) 0%, #FFFFFF 78%)",
        }
      : { borderColor: "var(--mantine-color-edr-border-6)" };

  return (
    <Paper withBorder radius="md" p="md" style={cardStyle}>
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Group gap={12} wrap="nowrap" style={{ minWidth: 0 }}>
          <ThemeIcon
            variant="light"
            color={isApproved ? "edr-green" : isQueried ? "red" : "gray"}
            radius="md"
            size={40}
          >
            {isApproved ? <CheckCircle2 size={19} /> : <FileText size={19} />}
          </ThemeIcon>
          <Box style={{ minWidth: 0 }}>
            <Text fz="14px" fw={700} c="edr-text" truncate>
              {doc.label}
              {doc.required ? " *" : ""}
            </Text>
            <Text fz="12px" c="edr-muted" truncate>
              {hasFile ? doc.file!.name : "Not uploaded by customer"}
            </Text>
            {isApproved && (reviewedAt || reviewerTeam) && (
              <Group gap={5} wrap="nowrap" mt={3}>
                <UserCheck size={12} color="var(--mantine-color-edr-green-7)" />
                <Text fz="11.5px" c="edr-green.8" fw={600} truncate>
                  Approved by {reviewerTeam}
                  {reviewedAt ? ` · ${reviewedAt}` : ""}
                </Text>
              </Group>
            )}
          </Box>
        </Group>

        <Group gap={8} wrap="nowrap">
          <Badge
            variant="light"
            color={meta.color}
            radius="sm"
            leftSection={
              isApproved ? (
                <CheckCircle2 size={11} />
              ) : isQueried ? (
                <MessageSquareWarning size={11} />
              ) : (
                <Clock size={11} />
              )
            }
          >
            {meta.label}
          </Badge>
          {hasFile &&
            isViewable({
              name: doc.file!.name,
              url: "",
            }) && (
              <Tooltip label="Preview document">
                <Button
                  size="compact-xs"
                  variant="default"
                  radius="md"
                  leftSection={<Eye size={13} />}
                  onClick={() =>
                    void fetchViewableFile(doc.file!.id, doc.file!.name).then(
                      onView,
                    )
                  }
                >
                  View
                </Button>
              </Tooltip>
            )}
          {hasFile && (
            <Tooltip label="Download">
              <Button
                component="button"
                type="button"
                onClick={() =>
                  void downloadBookingFile(doc.file!.id, doc.file!.name)
                }
                size="compact-xs"
                variant="default"
                radius="md"
                leftSection={<Download size={13} />}
              >
                Download
              </Button>
            </Tooltip>
          )}
        </Group>
      </Group>

      {isQueried && doc.note && (
        <Alert
          mt="sm"
          color="red"
          variant="light"
          radius="md"
          icon={<MessageSquareWarning size={15} />}
          p="xs"
        >
          <Text fz="12.5px" c="red.9">
            {doc.note}
          </Text>
        </Alert>
      )}

      {!readOnly && hasFile && (
        <Box mt="sm">
          {!queryOpen ? (
            <Group justify="flex-end" gap={8}>
              {!queriesLocked && (
                <Button
                  size="sm"
                  variant="light"
                  color="red"
                  radius="md"
                  leftSection={<MessageSquareWarning size={15} />}
                  disabled={busy}
                  onClick={() => onToggleQuery(true)}
                >
                  Open query
                </Button>
              )}
              {!isApproved && !approvalsLocked && (
                <Button
                  size="sm"
                  color="edr-green"
                  radius="md"
                  leftSection={<CheckCircle2 size={15} />}
                  disabled={busy}
                  onClick={onApprove}
                >
                  Approve
                </Button>
              )}
            </Group>
          ) : (
            <Box
              p="sm"
              style={{
                borderRadius: 12,
                background: "var(--mantine-color-red-0)",
                border: "1px solid var(--mantine-color-red-2)",
              }}
            >
              <Group gap={6} mb={6}>
                <MessageSquareWarning
                  size={14}
                  color="var(--mantine-color-red-7)"
                />
                <Text fz="12.5px" fw={700} c="red.8">
                  Describe the problem for the customer
                </Text>
              </Group>
              <Textarea
                placeholder="e.g. The commercial invoice is missing the HS code."
                value={note}
                onChange={(e) => onNote(e.currentTarget.value)}
                autosize
                minRows={2}
                radius="md"
                size="sm"
                autoFocus
              />
              <Group justify="flex-end" gap={8} mt={8}>
                <Button
                  size="sm"
                  variant="subtle"
                  color="gray"
                  radius="md"
                  disabled={busy}
                  onClick={() => onToggleQuery(false)}
                >
                  Cancel
                </Button>
                <Button
                  size="sm"
                  color="red"
                  radius="md"
                  leftSection={<MessageSquareWarning size={15} />}
                  loading={busy}
                  disabled={!note.trim()}
                  onClick={onQuery}
                >
                  Send query to customer
                </Button>
              </Group>
            </Box>
          )}
        </Box>
      )}
    </Paper>
  );
}
