import { useMemo, useState } from "react";
import { Alert, Box, Button, Group, Stack, Text } from "@mantine/core";
import { useQuery } from "@tanstack/react-query";
import {
  Building2,
  ClipboardList,
  Download,
  Eye,
  FileText,
  Info,
} from "lucide-react";

import type { Freight } from "@edr/types";
import { isViewable } from "@edr/ui-common";

import { api } from "@/services/api";
import { fetchViewableFile, downloadStoredFile } from "@/services/files.service";
import { warehouseService } from "@/services/warehouse.service";
import { useFileViewer } from "@/hooks/useFileViewer";
import { BookingActionModal } from "@/pages/bookings/clearance/BookingActionModal";
import { getBookingNextAction } from "@/pages/bookings/clearance/bookingNextAction";
import { ClearanceUploadedDocumentsPanel } from "@/components/contracts/ClearanceUploadedDocumentsPanel";

import toast from "react-hot-toast";

import { bookingsService } from "@/services/bookings.service";
import { saveBlob } from "@/utils/download";
import { IconSquare } from "./Documents";
import { CardTitle, SectionCard } from "./layout";

const BORDER = "#E6ECF2";

type AnyFile = {
  id: string;
  code: string;
  name: string;
  url: string;
  signedUrl?: string | null;
};

// ── shared row chrome ─────────────────────────────────────────────────────────

type PillTone = "green" | "red" | "blue" | "gray";

const PILL_TONES: Record<PillTone, { bg: string; fg: string; border?: string }> =
  {
    green: { bg: "#ECF6F1", fg: "#0A6F4D", border: "#CDEBDD" },
    red: { bg: "#FBEAE7", fg: "#A93226", border: "#F3C8C1" },
    blue: { bg: "#EAF1FB", fg: "#2E5B96" },
    gray: { bg: "#F1F4F7", fg: "#6B7C8E" },
  };

function Pill({ tone, label }: { tone: PillTone; label: string }) {
  const t = PILL_TONES[tone];
  return (
    <Box
      component="span"
      style={{
        display: "inline-flex",
        flexShrink: 0,
        borderRadius: 999,
        backgroundColor: t.bg,
        border: t.border ? `1px solid ${t.border}` : undefined,
        padding: "4px 10px",
        fontSize: 11.5,
        fontWeight: 700,
        color: t.fg,
        whiteSpace: "nowrap",
      }}
    >
      {label}
    </Box>
  );
}

function reviewPill(doc: Freight.ClearanceDocument) {
  if (!doc.file) return <Pill tone="gray" label="Not uploaded" />;
  switch (doc.reviewStatus) {
    case "APPROVED":
      return <Pill tone="green" label="Approved" />;
    case "QUERIED":
      return <Pill tone="red" label="Query — re-upload" />;
    default:
      return <Pill tone="blue" label="Pending review" />;
  }
}

/** One document row: icon tile, title/meta, status pill, view/download. */
function FileRow({
  title,
  meta,
  file,
  pill,
  last,
  onView,
}: {
  title: string;
  meta?: string | null;
  file: { id: string; name: string } | null;
  pill?: React.ReactNode;
  last?: boolean;
  onView: (f: { name: string; url: string }) => void;
}) {
  return (
    <Group
      gap={13}
      align="center"
      wrap="nowrap"
      py={12}
      style={{ borderBottom: last ? undefined : "1px solid #F2F5F8" }}
    >
      <Box
        style={{
          flexShrink: 0,
          width: 40,
          height: 40,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          borderRadius: 10,
          backgroundColor: file ? "#EAF1FB" : "#F1F4F7",
          color: file ? "#2E5B96" : "#9AA8B5",
        }}
      >
        <FileText size={20} />
      </Box>
      <Box miw={0} flex={1}>
        <Text truncate fz="13.5px" fw={700} c={file ? "#10202F" : "#6B7C8E"}>
          {title}
        </Text>
        <Text truncate fz="12px" c="#9AA8B5">
          {meta || file?.name || "—"}
        </Text>
      </Box>
      {pill}
      {file && isViewable({ name: file.name, url: "" }) && (
        <IconSquare
          icon={<Eye size={15} />}
          onClick={() => void fetchViewableFile(file.id, file.name).then(onView)}
        />
      )}
      {file && (
        <IconSquare
          icon={<Download size={15} />}
          onClick={() => void downloadStoredFile(file.id, file.name)}
        />
      )}
    </Group>
  );
}



// ── contract & profile document grouping ─────────────────────────────────────

// Mirrors ContractDetailPage's grouping: onboarding/profile codes seeded by
// file-upload-settings vs the generated contract PDF vs everything else.
const BUSINESS_LICENSE_DOC_CODES = new Set([
  "business_license",
  "commercial_license",
  "investment_license",
  "trade_license",
]);

// Licences carried from the company profile are suffixed per file
// (`business_license_1`), so match on the stripped base code too.
const isBusinessLicenseCode = (code: string): boolean =>
  BUSINESS_LICENSE_DOC_CODES.has(code) ||
  BUSINESS_LICENSE_DOC_CODES.has(code.replace(/_\d+$/, ""));
const PROFILE_DOC_CODES = new Set([
  "tin_certificate",
  "national_id",
  "national_id_passport",
  "passport",
]);

const KNOWN_FILE_LABELS: Record<string, string> = {
  contract: "Signed contract",
  tin_certificate: "TIN certificate",
  business_license: "Business licence",
  commercial_license: "Commercial licence",
  investment_license: "Investment licence",
  national_id: "National ID",
  national_id_passport: "National ID / Passport",
  passport: "Passport",
  commercial_invoice: "Commercial Invoice",
  packing_list: "Packing List",
  certificate_of_origin: "Certificate of Origin",
  letter_of_credit: "Letter of Credit / LC",
};

function fileLabel(f: AnyFile) {
  if (KNOWN_FILE_LABELS[f.code]) return KNOWN_FILE_LABELS[f.code];
  // Profile documents carried onto the contract are suffixed per file
  // (`business_license_2`) — label them from the base code, numbered.
  const base = f.code.replace(/_\d+$/, "");
  if (KNOWN_FILE_LABELS[base]) {
    const n = f.code.slice(base.length + 1);
    return n && n !== "1"
      ? `${KNOWN_FILE_LABELS[base]} ${n}`
      : KNOWN_FILE_LABELS[base];
  }
  // Ad-hoc uploads carry a generated code (custom_<ts>_<i>) — use the filename.
  if (f.code.startsWith("custom_")) return f.name;
  return f.code
    .replace(/_/g, " ")
    .replace(/\b\w/g, (m) => m.toUpperCase());
}

// ── the tab ───────────────────────────────────────────────────────────────────

/**
 * Documents tab of the booking detail page. Pulls together every document that
 * belongs to this shipment, in sections:
 *
 *  1. Clearance documents — the per-booking clearance grid (your uploads with
 *     their review state, GL output documents), the customs progress timeline,
 *     and the phased customs files (declaration, duty, transit permit, DO).
 *  2. Contract & company documents — the signed contract plus the company
 *     documents the contract carries from your profile (TIN certificate,
 *     business licence, national ID, …).
 *  3. Other booking documents — anything uploaded directly on the booking that
 *     isn't already shown above.
 */
export function DocumentsTab({ booking }: { booking: Freight.IBooking }) {
  const { view, viewer } = useFileViewer();
  const [modalOpen, setModalOpen] = useState(false);

  const hasContract = Boolean(booking.contractId);

  const { data: clearance } = useQuery(
    api.bookings.getClearance.queryOptions({
      input: { id: booking.id },
      enabled: hasContract,
    }),
  );

  const { data: contract } = useQuery(
    api.contracts.get.queryOptions({
      input: { id: booking.contractId ?? "" },
      enabled: hasContract,
    }),
  );

  const { data: handovers = [] } = useQuery({
    queryKey: ["bookingHandovers", booking.id],
    queryFn: () => warehouseService.bookingHandovers(booking.id),
  });

  const customerDocs = useMemo(
    () => (clearance?.documents ?? []).filter((d) => d.uploadedBy === "customer"),
    [clearance],
  );
  const glDocs = useMemo(
    () =>
      (clearance?.documents ?? []).filter(
        (d) => d.uploadedBy === "gl" && d.file,
      ),
    [clearance],
  );

  // The clearance action button (upload / re-upload / view) mirrors the
  // Overview tab's ClearanceCard so documents can be managed from here too.
  const action = getBookingNextAction(booking);
  const showManage = action && action.kind !== "BOOK";

  const contractFiles = (contract?.files ?? []) as AnyFile[];
  const contractPdf = contractFiles.find((f) => f.code === "contract");
  const licenseFiles = contractFiles.filter((f) =>
    isBusinessLicenseCode(f.code),
  );
  const profileFiles = contractFiles.filter((f) => PROFILE_DOC_CODES.has(f.code));

  // Booking files not already represented in the clearance grid (those rows
  // show review state, so they win) and not contract signatures/PDF.
  const clearanceKeys = useMemo(
    () => new Set((clearance?.documents ?? []).map((d) => d.fileKey)),
    [clearance],
  );
  const otherBookingFiles = ((booking.files ?? []) as AnyFile[]).filter(
    (f) => !clearanceKeys.has(f.code) && !f.code.startsWith("signature_"),
  );

  const company = contract?.company;

  // One-click warehouse-document bundle: GRN + gate clearance + handover.
  const [bundleBusy, setBundleBusy] = useState(false);
  const downloadWarehouseDocuments = async () => {
    setBundleBusy(true);
    const ref = booking.reference ?? booking.id;
    const jobs: Array<{ name: string; fn: () => Promise<Blob> }> = [
      { name: `GRN-${ref}.pdf`, fn: () => bookingsService.downloadBookingGrnDocument(booking.id) },
      {
        name: `gate-clearance-${ref}.pdf`,
        fn: () => bookingsService.downloadBookingReleaseDocument(booking.id),
      },
      {
        name: `handover-${ref}.pdf`,
        fn: () => bookingsService.downloadBookingHandoverDocument(booking.id),
      },
    ];
    let saved = 0;
    for (const job of jobs) {
      try {
        saveBlob(await job.fn(), job.name);
        saved += 1;
      } catch {
        // Document not available for this booking yet — skip it.
      }
    }
    setBundleBusy(false);
    if (saved === 0) {
      toast.error("No warehouse documents are available for this booking yet.");
    } else {
      toast.success(`Downloaded ${saved} document${saved !== 1 ? "s" : ""}.`);
    }
  };

  return (
    <Stack gap="lg">
      {/* ── 1. Clearance documents ──────────────────────────────────────── */}
      {hasContract && clearance && (
        <SectionCard>
          <Group justify="space-between" align="center" mb={4}>
            <CardTitle>Clearance documents</CardTitle>
            {showManage && (
              <Button
                color="edr-green"
                radius="md"
                size="xs"
                leftSection={<ClipboardList size={14} />}
                onClick={() => setModalOpen(true)}
              >
                {action.label}
              </Button>
            )}
          </Group>
          <Text fz="12.5px" c="dimmed" mb="sm">
            Documents required to clear this shipment, with their review state.
          </Text>

          {customerDocs.length > 0 ? (
            <Stack gap={0}>
              {customerDocs.map((doc, i) => (
                <FileRow
                  key={doc.fileKey}
                  title={`${doc.label}${doc.required ? " *" : ""}`}
                  meta={doc.note ? `Note: ${doc.note}` : doc.file?.name}
                  file={doc.file}
                  pill={reviewPill(doc)}
                  last={i === customerDocs.length - 1 && glDocs.length === 0}
                  onView={view}
                />
              ))}
              {glDocs.map((doc, i) => (
                <FileRow
                  key={doc.fileKey}
                  title={doc.label}
                  meta="Provided by Global Logistics"
                  file={doc.file}
                  pill={<Pill tone="green" label="Available" />}
                  last={i === glDocs.length - 1}
                  onView={view}
                />
              ))}
            </Stack>
          ) : (
            <Alert color="gray" radius="md" icon={<Info size={16} />}>
              No clearance documents are required for this booking.
            </Alert>
          )}
        </SectionCard>
      )}

      {/* Customs progress lives in the unified journey wizard at the top of
          the page (StatusHero → JourneyWizard) — no duplicate timeline here. */}
      {(clearance?.workflowFiles?.length ?? 0) > 0 && (
        <SectionCard>
          <CardTitle>Customs documents</CardTitle>
          <Box mt="md">
            <ClearanceUploadedDocumentsPanel
              embedded
              files={clearance!.workflowFiles ?? []}
              tradeDirection={booking.tradeDirection}
              onView={(f) => view(f)}
              onDownload={({ id, name }) => void downloadStoredFile(id, name)}
            />
          </Box>
        </SectionCard>
      )}

      {/* ── 2. Contract & company documents ─────────────────────────────── */}
      {hasContract && contract && (
        <SectionCard>
          <Group gap={10} align="center" mb={4}>
            <Building2 size={16} color="#6B7C8E" />
            <CardTitle>Contract & company documents</CardTitle>
          </Group>
          <Text fz="12.5px" c="dimmed" mb="sm">
            Attached to contract {contract.reference} — including the company
            documents it carries from your profile (TIN, licence, ID).
          </Text>

          {(company?.name || company?.tin) && (
            <Group
              gap={24}
              mb="sm"
              px={14}
              py={10}
              style={{ borderRadius: 10, border: `1px solid ${BORDER}` }}
            >
              {company?.name && (
                <Box>
                  <Text fz="10.5px" fw={700} c="#6B7C8E" tt="uppercase">
                    Company
                  </Text>
                  <Text fz="13.5px" fw={700} c="#10202F">
                    {company.name}
                  </Text>
                </Box>
              )}
              {company?.tin && (
                <Box>
                  <Text fz="10.5px" fw={700} c="#6B7C8E" tt="uppercase">
                    TIN number
                  </Text>
                  <Text fz="13.5px" fw={700} c="#10202F">
                    {company.tin}
                  </Text>
                </Box>
              )}
            </Group>
          )}

          {contractPdf || licenseFiles.length || profileFiles.length ? (
            <Stack gap={0}>
              {contractPdf && (
                <FileRow
                  title="Signed contract"
                  meta={contractPdf.name}
                  file={contractPdf}
                  pill={<Pill tone="green" label="Executed" />}
                  last={!licenseFiles.length && !profileFiles.length}
                  onView={view}
                />
              )}
              {[...licenseFiles, ...profileFiles].map((f, i, arr) => (
                <FileRow
                  key={f.id}
                  title={fileLabel(f)}
                  meta={
                    PROFILE_DOC_CODES.has(f.code) ||
                    isBusinessLicenseCode(f.code)
                      ? "From your company profile"
                      : f.name
                  }
                  file={f}
                  pill={<Pill tone="green" label="On file" />}
                  last={i === arr.length - 1}
                  onView={view}
                />
              ))}
            </Stack>
          ) : (
            <Alert color="gray" radius="md" icon={<Info size={16} />}>
              No documents are attached to this contract yet.
            </Alert>
          )}
        </SectionCard>
      )}

      {/* ── 3. Other booking documents ──────────────────────────────────── */}
      {otherBookingFiles.length > 0 && (
        <SectionCard>
          <CardTitle>Other booking documents</CardTitle>
          <Text fz="12.5px" c="dimmed" mt={4} mb="sm">
            Documents uploaded directly on this booking.
          </Text>
          <Stack gap={0}>
            {otherBookingFiles.map((f, i) => (
              <FileRow
                key={f.id}
                title={fileLabel(f)}
                meta={f.name}
                file={f}
                pill={<Pill tone="green" label="Uploaded" />}
                last={i === otherBookingFiles.length - 1}
                onView={view}
              />
            ))}
          </Stack>
        </SectionCard>
      )}

      {/* ── 4. Handover signatures ──────────────────────────────────────── */}
      {handovers.length > 0 && (
        <SectionCard>
          <CardTitle>Handover signatures</CardTitle>
          <Text fz="12.5px" c="dimmed" mt={4} mb="sm">
            Records of goods handover and customer signatures.
          </Text>
          <Stack gap={0}>
            {handovers.map((h, i) => (
              <Box
                key={h.id}
                px="md"
                py="sm"
                style={{
                  borderBottom:
                    i !== handovers.length - 1
                      ? `1px solid ${BORDER}`
                      : "none",
                }}
              >
                <Group justify="space-between" align="flex-start">
                  <Box>
                    <Text fw={500} fz="14px">
                      {h.reference}
                    </Text>
                    <Text fz="12.5px" c="dimmed" mt={2}>
                      {h.mileType === "SELF_HAUL"
                        ? "Customer truck delivery"
                        : `EDR delivery${h.truckPlate ? ` (${h.truckPlate})` : ""}`}
                    </Text>
                    {h.signedAt && (
                      <Text fz="12.5px" c="dimmed" mt={1}>
                        Signed by {h.signerName || "Unknown"} on{" "}
                        {new Date(h.signedAt).toLocaleDateString()}
                      </Text>
                    )}
                  </Box>
                  <Pill
                    tone={h.signedAt ? "green" : "blue"}
                    label={h.signedAt ? "Signed" : "Pending signature"}
                  />
                </Group>
                {h.signedAt && h.signatureImageUrl && (
                  <Box mt="sm">
                    <img
                      src={h.signatureImageUrl}
                      alt="Signature"
                      style={{
                        maxHeight: "60px",
                        maxWidth: "200px",
                        border: `1px solid ${BORDER}`,
                        borderRadius: "4px",
                        padding: "4px",
                      }}
                    />
                  </Box>
                )}
              </Box>
            ))}
          </Stack>
        </SectionCard>
      )}

      {/* ── Warehouse documents (one-click bundle) ──────────────────────── */}
      <SectionCard>
        <CardTitle>Warehouse documents</CardTitle>
        <Text fz="12.5px" c="dimmed" mt={4} mb="sm">
          Goods Received Note, gate clearance / release order and handover — download all
          available documents for this booking in one click.
        </Text>
        <Button
          leftSection={<Download size={16} />}
          color="edr-green"
          loading={bundleBusy}
          onClick={downloadWarehouseDocuments}
        >
          Download documents
        </Button>
      </SectionCard>

      {!hasContract && otherBookingFiles.length === 0 && (
        <SectionCard>
          <Alert color="gray" radius="md" icon={<Info size={16} />}>
            No documents have been uploaded for this booking yet.
          </Alert>
        </SectionCard>
      )}

      {showManage && (
        <BookingActionModal
          booking={booking}
          opened={modalOpen}
          onClose={() => setModalOpen(false)}
        />
      )}
      {viewer}
    </Stack>
  );
}
