import { directionLabel } from "@/lib/utils";
import {
  Fragment,
  useCallback,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";
import { useNavigate } from "react-router-dom";
import {
  ActionIcon,
  Badge,
  Box,
  Button,
  Card,
  Group,
  Menu,
  SegmentedControl,
  Stack,
  Text,
  TextInput,
  ThemeIcon,
  Tooltip,
} from "@mantine/core";
import {
  ArrowRight,
  Calendar,
  ChevronRight,
  ExternalLink,
  Eye,
  FileText,
  Inbox,
  LayoutGrid,
  MoreHorizontal,
  PackageCheck,
  PackagePlus,
  RefreshCw,
  Search,
  ShieldCheck,
  ShipWheel,
  Table as TableIcon,
  Truck,
  User,
  X,
} from "lucide-react";
import {
  DataTable,
  DataTableFooter,
  usePagination,
  type ColumnDef,
} from "@edr/ui-common";
import type { Freight } from "@edr/types";

import { PageContainer } from "@/components/page/PageContainer";
import { PageHeader } from "@/components/page/PageHeader";
import { KpiStrip } from "@/components/page/KpiStrip";
import { bookingTable } from "@/components/bookings/booking-ui.styles";
import { useAuth } from "@/auth/useAuth";
import { useContractClearanceQueue } from "@/hooks/contracts/useContracts";
import { useBookingEtClearanceQueue } from "@/hooks/bookings/useBookings";
import type { BookingDetail } from "@/types/booking";
import { FREIGHT_PERMS, hasPermission, isDjiboutiGl } from "@/lib/permissions";
import { GlUpcomingWindowsSection } from "@/components/contracts/GlUpcomingWindowsSection";
import {
  RequestedCargoChips,
  summarizeRequestedCargo,
} from "@/features/clearance/requestedCargo";
import { contractsService } from "@/services/contracts.service";
import { useQuery } from "@tanstack/react-query";

type ViewMode = "table" | "cards";
type QueueTab = "all" | "shipments";

/** Persist the selected queue tab so returning from a detail keeps it. */
const QUEUE_TAB_STORAGE_KEY = "edr.clearance.queueTab";

interface ClearanceRow {
  id: string;
  reference: string;
  customerLabel: string;
  tradeDirection: string;
  freightType: string;
  originLabel: string;
  destinationLabel: string;
  /** Full ordered corridor across the contract's route legs (origin → … → destination). */
  routeStops: string[];
  contractKind: string;
  serviceTypeName: string;
  customs: boolean;
  status: string;
  /** true once GL has finalized clearance — customer may book in the portal. */
  ready: boolean;
  /** true once GL Ethiopia created the shipment booking. */
  bookingCreated: boolean;
  /** true when the created booking EXPIRED unpaid — GL must rebook. */
  paymentExpired: boolean;
  /** The expired booking, so rebook can copy its cargo. */
  expiredBookingId: string | null;
}

function yardLabel(
  yard?: { label?: string; code?: string; name?: string } | null,
  fallback = "—",
): string {
  if (!yard) return fallback;
  return yard.label ?? yard.name ?? yard.code ?? fallback;
}

/**
 * Chain the contract's ordered route legs into one corridor of stops —
 * origin of the first leg, then each leg's destination (Djibouti → Adama →
 * Dire Dawa). A leg whose origin differs from the previous destination inserts
 * that stop too, so gapped route lists stay readable.
 */
function contractRouteStops(routes: Freight.IContractRoute[]): string[] {
  const stops: string[] = [];
  for (const r of routes) {
    const origin = yardLabel(r.originYard);
    const destination = yardLabel(r.destinationYard);
    if (stops.length === 0 || stops[stops.length - 1] !== origin) {
      stops.push(origin);
    }
    stops.push(destination);
  }
  return stops;
}

function toClearanceRow(contract: Freight.IContract): ClearanceRow {
  const routes = [...(contract.routes ?? [])].sort(
    (a, b) => a.sortOrder - b.sortOrder,
  );
  const first = routes[0];
  const last = routes[routes.length - 1] ?? first;
  return {
    id: contract.id,
    reference: contract.reference,
    // The queue joins the company relation — show its name, never the raw uuid.
    customerLabel: contract.isGovernment
      ? (contract.governmentInstitution ?? "Government")
      : (contract.company?.name ?? "—"),
    tradeDirection: contract.tradeDirection ?? "—",
    freightType: contract.freightType ?? "—",
    originLabel: yardLabel(first?.originYard),
    destinationLabel: yardLabel(last?.destinationYard),
    routeStops: contractRouteStops(routes),
    contractKind: contract.contractKind,
    serviceTypeName: contract.serviceType?.serviceName ?? "—",
    customs:
      contract.serviceType?.includesCustoms ?? contract.customsClearingEnabled,
    status: contract.status,
    ready: contract.status === "CLEARANCE_READY_FOR_BOOKING",
    bookingCreated: contract.status === "ACTIVE_SHIPMENT_IN_PROGRESS",
    paymentExpired:
      contract.status === "ACTIVE_SHIPMENT_IN_PROGRESS" &&
      contract.latestCycleBookingStatus === "EXPIRED",
    expiredBookingId:
      contract.latestCycleBookingStatus === "EXPIRED"
        ? (contract.latestCycleBookingId ?? null)
        : null,
  };
}

function CustomsBadge({ customs }: { customs: boolean }) {
  return customs ? (
    <Badge
      size="xs"
      variant="light"
      color="edr-green"
      radius="sm"
      leftSection={<ShieldCheck size={11} />}
    >
      Customs
    </Badge>
  ) : (
    <Badge size="xs" variant="light" color="gray" radius="sm">
      No customs
    </Badge>
  );
}

function DirectionIcon({ direction }: { direction: string }) {
  const isImport = direction === "IMPORT";
  const Icon = isImport ? Truck : ShipWheel;
  const label = directionLabel(direction);
  return (
    <Tooltip label={label} withArrow>
      <ThemeIcon
        variant="light"
        color={isImport ? "edr-green" : "gray"}
        radius="md"
        size={28}
        aria-label={label}
      >
        <Icon size={15} strokeWidth={1.9} />
      </ThemeIcon>
    </Tooltip>
  );
}

function StatusBadge({ row }: { row: ClearanceRow }) {
  // Terminal contracts stay listed as history — badge the terminal state
  // instead of falling through to "Under review".
  if (["EXPIRED", "CANCELLED", "REJECTED"].includes(row.status)) {
    return (
      <Tooltip
        label="This contract is no longer active — kept here for clearance history."
        withArrow
      >
        <Badge
          size="sm"
          variant="light"
          color={row.status === "EXPIRED" ? "orange" : "red"}
          radius="sm"
        >
          {row.status === "EXPIRED"
            ? "Contract expired"
            : row.status === "CANCELLED"
              ? "Cancelled"
              : "Rejected"}
        </Badge>
      </Tooltip>
    );
  }
  if (row.paymentExpired) {
    return (
      <Tooltip
        label="The customer did not pay in time — the booking expired. GL rebooks on the customer's behalf."
        withArrow
      >
        <Badge
          size="sm"
          variant="light"
          color="orange"
          radius="sm"
          leftSection={<RefreshCw size={12} />}
        >
          Payment expired
        </Badge>
      </Tooltip>
    );
  }
  if (row.bookingCreated) {
    return (
      <Tooltip label="GL Ethiopia created the shipment booking" withArrow>
        <Badge
          size="sm"
          variant="light"
          color="blue"
          radius="sm"
          leftSection={<PackagePlus size={12} />}
        >
          Booking created
        </Badge>
      </Tooltip>
    );
  }
  if (row.ready) {
    return (
      <Tooltip
        label="Document approval finalized — the customer creates the booking in the portal"
        withArrow
      >
        <Badge
          size="sm"
          variant="light"
          color="edr-green"
          radius="sm"
          leftSection={<PackageCheck size={12} />}
        >
          Documents approved
        </Badge>
      </Tooltip>
    );
  }
  return (
    <Badge size="sm" variant="light" color="yellow" radius="sm">
      Under review
    </Badge>
  );
}

/**
 * Document Clearance hub. Lists every customs (Path B) contract in phased clearance,
 * including after booking is created — stays visible for reference and follow-up.
 */
export default function ContractClearanceListPage() {
  const navigate = useNavigate();
  const { user } = useAuth();
  const canReview = hasPermission(user, FREIGHT_PERMS.contracts.clearanceReview);
  const canEt = hasPermission(user, FREIGHT_PERMS.contracts.clearanceEtActions);
  // Creating a booking under a cleared contract is a GL Ethiopia action — never
  // available to Djibouti GL.
  const canCreateBooking =
    hasPermission(user, FREIGHT_PERMS.contracts.createBooking) &&
    !isDjiboutiGl(user);

  const defaultQueue: QueueTab = canReview ? "all" : "shipments";
  const [queueTab, setQueueTab] = useState<QueueTab>(() => {
    const stored =
      typeof window !== "undefined"
        ? window.localStorage.getItem(QUEUE_TAB_STORAGE_KEY)
        : null;
    return stored === "all" || stored === "shipments" ? stored : defaultQueue;
  });
  const [query, setQuery] = useState("");
  const [view, setView] = useState<ViewMode>("table");
  const { pagination, setPagination } = usePagination({ pageSize: 10 });

  const selectQueueTab = useCallback((tab: QueueTab) => {
    setQueueTab(tab);
    if (typeof window !== "undefined") {
      window.localStorage.setItem(QUEUE_TAB_STORAGE_KEY, tab);
    }
  }, []);

  // Contract clearance rows feed both the Contracts tab and the header KPIs, so
  // they load regardless of the active tab.
  const { data: allData, isLoading: allLoading, isError: allError, isFetching: allFetching, refetch: refetchAll } =
    useContractClearanceQueue(true);
  const {
    data: bookingQueue,
    isLoading: bookingsLoading,
    isError: bookingsError,
    isFetching: bookingsFetching,
    refetch: refetchBookings,
  } = useBookingEtClearanceQueue(queueTab === "shipments");

  const data = allData;
  const isLoading = queueTab === "shipments" ? bookingsLoading : allLoading;
  const isError = queueTab === "shipments" ? bookingsError : allError;
  const isFetching = queueTab === "shipments" ? bookingsFetching : allFetching;
  const refetch = () => {
    if (queueTab === "shipments") void refetchBookings();
    else void refetchAll();
  };

  const queueTabOptions = useMemo(() => {
    const opts: { value: QueueTab; label: ReactNode }[] = [];
    if (canReview) {
      opts.push({
        value: "all",
        label: (
          <Group gap={6} wrap="nowrap">
            <FileText size={15} />
            <Box visibleFrom="sm">Contracts</Box>
          </Group>
        ),
      });
    }
    if (canReview || canEt) {
      opts.push({
        value: "shipments",
        label: (
          <Group gap={6} wrap="nowrap">
            <PackageCheck size={15} />
            <Box visibleFrom="sm">Shipments</Box>
          </Group>
        ),
      });
    }
    return opts;
  }, [canReview, canEt]);

  // If a persisted/default tab isn't available for this user, fall back to the
  // first permitted tab.
  useEffect(() => {
    if (
      queueTabOptions.length > 0 &&
      !queueTabOptions.some((o) => o.value === queueTab)
    ) {
      selectQueueTab(queueTabOptions[0].value);
    }
  }, [queueTabOptions, queueTab, selectQueueTab]);

  // Shipment requests carry the requested quantities (per container type, or
  // bulk weight/items). Map them onto the booking rows by createdBookingId so
  // the queue shows what each shipment was requested for.
  const { data: requestQueue } = useQuery({
    queryKey: ["shipment-request-queue"],
    queryFn: () => contractsService.getBookingRequestQueue(),
    enabled: queueTab === "shipments",
  });
  const requestedByBooking = useMemo(() => {
    const map = new Map<string, Freight.RequestedShipmentLines>();
    for (const req of requestQueue ?? []) {
      if (req.createdBookingId) map.set(req.createdBookingId, req.requestedLines);
    }
    return map;
  }, [requestQueue]);

  // GENERAL-contract shipment bookings in per-booking clearance.
  const bookingRows = useMemo(() => {
    const rows: ShipmentBookingRow[] = (bookingQueue ?? []).map((b: BookingDetail) => ({
      id: b.id,
      reference: b.reference,
      customerLabel: b.company?.name ?? b.governmentInstitution ?? "—",
      originLabel: b.originYard?.name ?? "—",
      destinationLabel: b.destinationYard?.name ?? "—",
      tradeDirection: b.tradeDirection ?? "—",
      freightType: b.freightType ?? "—",
      status: b.status,
      requested: requestedByBooking.get(b.id) ?? null,
      contractId: b.contractId ?? null,
      contractReference: b.contractReference ?? null,
      contractKind: b.contractKind ?? null,
      customs: b.serviceType?.includesCustoms ?? Boolean(b.customsClearingEnabled),
      createdAt: b.createdAt ?? null,
      // A bare initiated instance has no cargo/price yet — GL still has to create
      // (complete) the booking.
      bookingCreated: Number(b.totalAmount ?? 0) > 0,
    }));
    const q = query.trim().toLowerCase();
    if (!q) return rows;
    return rows.filter(
      (r) =>
        r.reference.toLowerCase().includes(q) ||
        r.customerLabel.toLowerCase().includes(q) ||
        (r.contractReference ?? "").toLowerCase().includes(q) ||
        r.originLabel.toLowerCase().includes(q) ||
        r.destinationLabel.toLowerCase().includes(q) ||
        summarizeRequestedCargo(r.requested).toLowerCase().includes(q),
    );
  }, [bookingQueue, query, requestedByBooking]);

  const allRows = useMemo(
    () => (data?.items ?? []).map(toClearanceRow),
    [data?.items],
  );

  const counts = useMemo(
    () => ({
      all: allRows.length,
      ready: allRows.filter((r) => r.ready).length,
      booked: allRows.filter((r) => r.bookingCreated).length,
      review: allRows.filter((r) => !r.ready && !r.bookingCreated).length,
    }),
    [allRows],
  );

  const rows = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return allRows;
    return allRows.filter(
      (r) =>
        r.reference.toLowerCase().includes(q) ||
        r.customerLabel.toLowerCase().includes(q) ||
        r.originLabel.toLowerCase().includes(q) ||
        r.destinationLabel.toLowerCase().includes(q),
    );
  }, [allRows, query]);

  const total = queueTab === "shipments" ? bookingRows.length : rows.length;
  const pageCount = Math.max(1, Math.ceil(total / pagination.pageSize));

  const pagedRows = useMemo(() => {
    const start = pagination.pageIndex * pagination.pageSize;
    return rows.slice(start, start + pagination.pageSize);
  }, [rows, pagination.pageIndex, pagination.pageSize]);

  const openDetail = useCallback(
    (id: string) => navigate(`/dashboard/contracts/clearance/${id}`),
    [navigate],
  );

  const columns: ColumnDef<ClearanceRow>[] = useMemo(
    () => [
      {
        id: "contract",
        header: () => <span className={bookingTable.headerCell}>Contract</span>,
        cell: ({ row }) => {
          const r = row.original;
          return (
            <div className="flex items-center gap-3 py-1.5">
              <div className={bookingTable.rowIcon}>
                <ShieldCheck className="size-4" strokeWidth={1.75} />
              </div>
              <div className="min-w-0">
                <p className="truncate font-medium text-foreground">
                  {r.reference}
                </p>
                <p className="mt-0.5 flex items-center gap-1 truncate text-xs text-muted-foreground">
                  <User className="size-3 shrink-0 opacity-70" />
                  {r.customerLabel}
                </p>
              </div>
            </div>
          );
        },
      },
      {
        id: "route",
        header: () => <span className={bookingTable.headerCell}>Route</span>,
        cell: ({ row }) => {
          const r = row.original;
          return (
            <Stack gap={4} py={2}>
              <Group gap={6} wrap="wrap">
                {(r.routeStops.length >= 2
                  ? r.routeStops
                  : [r.originLabel, r.destinationLabel]
                ).map((stop, i) => (
                  <Fragment key={i}>
                    {i > 0 ? (
                      <ArrowRight
                        size={14}
                        className="shrink-0 text-muted-foreground"
                      />
                    ) : null}
                    <Text size="sm" fw={500}>
                      {stop}
                    </Text>
                  </Fragment>
                ))}
              </Group>
              <Group gap={8} align="center">
                <DirectionIcon direction={r.tradeDirection} />
                <Badge size="xs" variant="default" radius="sm">
                  {r.freightType}
                </Badge>
              </Group>
            </Stack>
          );
        },
      },
      {
        id: "kind",
        header: () => <span className={bookingTable.headerCell}>Kind</span>,
        cell: ({ row }) => (
          <Badge size="xs" variant="default" radius="sm" tt="uppercase">
            {row.original.contractKind === "GENERAL" ? "General" : "One-time"}
          </Badge>
        ),
      },
      {
        id: "service",
        header: () => <span className={bookingTable.headerCell}>Service</span>,
        cell: ({ row }) => {
          const r = row.original;
          return (
            <Stack gap={4} py={2} style={{ minWidth: 0 }}>
              <Text size="sm" fw={500} truncate maw={160}>
                {r.serviceTypeName}
              </Text>
              <CustomsBadge customs={r.customs} />
            </Stack>
          );
        },
      },
      {
        id: "status",
        header: () => <span className={bookingTable.headerCell}>Status</span>,
        cell: ({ row }) => <StatusBadge row={row.original} />,
      },
      {
        id: "go",
        size: 150,
        cell: ({ row }) =>
          row.original.ready && canCreateBooking ? (
            <Group justify="flex-end" pr="xs">
              <Button
                size="compact-sm"
                color="edr-green"
                radius="md"
                leftSection={<PackagePlus size={14} />}
                onClick={(e) => {
                  e.stopPropagation();
                  navigate(
                    `/dashboard/contracts/${row.original.id}/create-booking`,
                  );
                }}
              >
                Create booking
              </Button>
            </Group>
          ) : row.original.paymentExpired && canCreateBooking ? (
            <Group justify="flex-end" pr="xs">
              <Button
                size="compact-sm"
                color="grape"
                radius="md"
                leftSection={<RefreshCw size={14} />}
                onClick={(e) => {
                  e.stopPropagation();
                  navigate(
                    `/dashboard/contracts/${row.original.id}/create-booking${
                      row.original.expiredBookingId
                        ? `?copyFrom=${row.original.expiredBookingId}`
                        : ""
                    }`,
                  );
                }}
              >
                Rebook
              </Button>
            </Group>
          ) : (
            <Group justify="flex-end" pr="xs">
              <ChevronRight size={16} className="text-muted-foreground" />
            </Group>
          ),
      },
    ],
    [navigate, canCreateBooking],
  );

  return (
    <PageContainer>
      <Stack gap="lg">
        <PageHeader
          title="Document Clearance"
          subtitle="All customs contracts in phased clearance — stays visible after booking is created."
          meta={
            <Badge
              variant="light"
              color="edr-green"
              radius="sm"
              leftSection={<ShieldCheck size={13} />}
            >
              {counts.all} in clearance
            </Badge>
          }
          action={
            <ActionIcon
              variant="default"
              size="lg"
              radius="md"
              onClick={() => refetch()}
              loading={isFetching}
              aria-label="Refresh"
            >
              <RefreshCw size={16} />
            </ActionIcon>
          }
        />

        <KpiStrip
          loading={isLoading}
          items={[
            {
              label: "In clearance",
              value: counts.all,
              icon: Inbox,
              color: "edr-green",
            },
            {
              label: "Awaiting review",
              value: counts.review,
              icon: ShieldCheck,
              color: "yellow",
            },
            {
              label: "Ready / booked",
              value: counts.ready + counts.booked,
              icon: PackageCheck,
              color: "edr-green",
            },
          ]}
        />

        <GlUpcomingWindowsSection />

        <Card p={0} withBorder shadow="sm" radius="lg">
          <Stack gap={0}>
            {queueTabOptions.length > 1 ? (
              <Box px="md" pt="md">
                <SegmentedControl
                  size="sm"
                  radius="md"
                  value={queueTab}
                  onChange={(v) => {
                    selectQueueTab(v as QueueTab);
                    setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
                  }}
                  data={queueTabOptions}
                />
              </Box>
            ) : null}
            <Box px="md" pt="md" pb="sm">
              <Group justify="space-between" gap="md" wrap="wrap">
                <TextInput
                  placeholder="Search reference, customer, or route…"
                  leftSection={<Search size={18} />}
                  value={query}
                  onChange={(e) => {
                    setQuery(e.currentTarget.value);
                    setPagination({
                      pageIndex: 0,
                      pageSize: pagination.pageSize,
                    });
                  }}
                  rightSection={
                    query ? (
                      <ActionIcon
                        size="sm"
                        color="gray"
                        radius="md"
                        variant="transparent"
                        onClick={() => setQuery("")}
                      >
                        <X size={16} />
                      </ActionIcon>
                    ) : null
                  }
                  radius="lg"
                  style={{ flex: 1, minWidth: 220 }}
                />
                <Group gap="sm" wrap="nowrap">
                  <Text size="sm" c="dimmed">
                    {total} record{total !== 1 ? "s" : ""}
                  </Text>
                  <SegmentedControl
                    size="sm"
                    radius="md"
                    value={view}
                    onChange={(v) => setView(v as ViewMode)}
                    data={[
                      {
                        value: "table",
                        label: (
                          <Group gap={6} wrap="nowrap">
                            <TableIcon size={15} />
                            <Box visibleFrom="sm">Table</Box>
                          </Group>
                        ),
                      },
                      {
                        value: "cards",
                        label: (
                          <Group gap={6} wrap="nowrap">
                            <LayoutGrid size={15} />
                            <Box visibleFrom="sm">Cards</Box>
                          </Group>
                        ),
                      },
                    ]}
                  />
                </Group>
              </Group>
            </Box>

            {queueTab === "shipments" ? (
              <ShipmentBookingsTable
                rows={bookingRows}
                loading={bookingsLoading}
                error={bookingsError}
                canCreateBooking={canCreateBooking}
                onOpen={(id) => navigate(`/dashboard/clearance/${id}`)}
                onCreateBooking={(row) =>
                  navigate(
                    `/dashboard/contracts/${row.contractId}/bookings/${row.id}/complete`,
                  )
                }
                onRebook={(row) =>
                  // Re-complete the SAME expired booking (new day, same finished
                  // per-booking clearance) — a fresh create-booking would spawn a
                  // new instance and force the customer through clearance + fee
                  // again.
                  navigate(
                    `/dashboard/contracts/${row.contractId}/bookings/${row.id}/complete?copyFrom=${row.id}`,
                  )
                }
                onViewContract={(contractId) =>
                  navigate(`/dashboard/contracts/clearance/${contractId}`)
                }
              />
            ) : view === "table" ? (
              <Box style={{ overflowX: "auto" }} px="xs" pb="xs">
                <DataTable<ClearanceRow, unknown>
                  columns={columns}
                  data={pagedRows}
                  status={
                    isLoading ? "loading" : isError ? "error" : "success"
                  }
                  onRowClick={(row) => openDetail(row.id)}
                  pagination={{
                    pageIndex: pagination.pageIndex,
                    pageSize: pagination.pageSize,
                    pageCount,
                    totalCount: total,
                  }}
                  tableOptions={{
                    state: { pagination },
                    onPaginationChange: setPagination,
                    manualPagination: true,
                    pageCount,
                  }}
                  containerClassName="border-0 shadow-none bg-transparent"
                  footer={DataTableFooter}
                />
              </Box>
            ) : (
              <ClearanceCardGrid
                rows={pagedRows}
                loading={isLoading}
                onOpen={openDetail}
              />
            )}
          </Stack>
        </Card>
      </Stack>
    </PageContainer>
  );
}

interface ShipmentBookingRow {
  id: string;
  reference: string;
  customerLabel: string;
  originLabel: string;
  destinationLabel: string;
  tradeDirection: string;
  freightType: string;
  status: string;
  /** Requested quantities from the originating shipment request. */
  requested: Freight.RequestedShipmentLines | null;
  /** Contract this shipment booking was created under. */
  contractId: string | null;
  contractReference: string | null;
  contractKind: "ONE_TIME" | "GENERAL" | null;
  customs: boolean;
  createdAt: string | null;
  /** true once GL has actually created (completed) the booking. */
  bookingCreated: boolean;
}

const formatDate = (iso: string | null) => {
  if (!iso) return "—";
  const d = new Date(iso);
  return Number.isNaN(d.getTime())
    ? "—"
    : d.toLocaleDateString(undefined, { day: "2-digit", month: "short", year: "numeric" });
};

const prettyStatus = (s: string) =>
  s
    .toLowerCase()
    .replace(/_/g, " ")
    .replace(/^\w/, (c) => c.toUpperCase());

const shipmentStatusColor = (s: string) => {
  if (s === "AWAITING_DOCUMENTS") return "yellow";
  if (s === "DOCUMENTS_UNDER_REVIEW") return "blue";
  if (s === "CLEARANCE_READY") return "edr-green";
  if (
    [
      "SELECTED_FOR_BATCH",
      "PNR_GENERATED",
      "AWAITING_PAYMENT",
      "PAYMENT_VERIFICATION_IN_PROGRESS",
    ].includes(s)
  )
    return "violet";
  if (s === "EXPIRED") return "orange";
  if (s === "CANCELLED" || s === "REJECTED") return "red";
  return "gray";
};

/** GENERAL-contract shipment bookings currently in per-booking clearance. */
function ShipmentBookingsTable({
  rows,
  loading,
  error,
  canCreateBooking,
  onOpen,
  onCreateBooking,
  onRebook,
  onViewContract,
}: {
  rows: ShipmentBookingRow[];
  loading: boolean;
  error: boolean;
  canCreateBooking: boolean;
  onOpen: (id: string) => void;
  onCreateBooking: (row: ShipmentBookingRow) => void;
  onRebook: (row: ShipmentBookingRow) => void;
  onViewContract: (contractId: string) => void;
}) {
  // A bare initiated instance that has cleared but not yet been created by GL.
  const isBookable = (r: ShipmentBookingRow) =>
    canCreateBooking &&
    Boolean(r.contractId) &&
    !r.bookingCreated &&
    r.status === "CLEARANCE_READY";

  // A customs shipment whose booking lost its slot — GL rebooks it (customer
  // can't self-rebook a customs booking). Copies the expired booking's cargo.
  const isRebookable = (r: ShipmentBookingRow) =>
    canCreateBooking &&
    Boolean(r.contractId) &&
    r.customs &&
    r.status === "EXPIRED";

  const columns = useMemo<ColumnDef<ShipmentBookingRow>[]>(
    () => [
      {
        id: "booking",
        header: () => <span className={bookingTable.headerCell}>Booking</span>,
        cell: ({ row }) => (
          <div className="flex items-center gap-3 py-1.5">
            <div className={bookingTable.rowIcon}>
              <PackageCheck className="size-4" strokeWidth={1.75} />
            </div>
            <div className="min-w-0">
              <p className="truncate font-medium text-foreground">
                {row.original.reference}
              </p>
              <p className="mt-0.5 flex items-center gap-1 truncate text-xs text-muted-foreground">
                <User className="size-3 shrink-0 opacity-70" />
                {row.original.customerLabel}
              </p>
            </div>
          </div>
        ),
      },
      {
        id: "contract",
        header: () => <span className={bookingTable.headerCell}>Contract</span>,
        cell: ({ row }) => {
          const r = row.original;
          return (
            <Stack gap={4} py={2}>
              <Group gap={6} wrap="nowrap">
                <FileText size={13} className="shrink-0 text-muted-foreground" />
                <Text size="sm" fw={500} truncate maw={150}>
                  {r.contractReference ?? "—"}
                </Text>
              </Group>
              {r.contractKind ? (
                <Badge size="xs" variant="default" radius="sm" tt="uppercase">
                  {r.contractKind === "GENERAL" ? "General" : "One-time"}
                </Badge>
              ) : null}
            </Stack>
          );
        },
      },
      {
        id: "route",
        header: () => <span className={bookingTable.headerCell}>Route</span>,
        cell: ({ row }) => (
          <Group gap={6} wrap="nowrap">
            <Text size="sm" className="truncate">
              {row.original.originLabel}
            </Text>
            <ArrowRight size={13} className="shrink-0 text-muted-foreground" />
            <Text size="sm" className="truncate">
              {row.original.destinationLabel}
            </Text>
          </Group>
        ),
      },
      {
        id: "kind",
        header: () => <span className={bookingTable.headerCell}>Type</span>,
        cell: ({ row }) => (
          <Group gap={6} wrap="nowrap">
            <Badge variant="light" color="gray" radius="sm">
              {prettyStatus(row.original.tradeDirection)}
            </Badge>
            <Badge variant="outline" color="gray" radius="sm">
              {prettyStatus(row.original.freightType)}
            </Badge>
            <CustomsBadge customs={row.original.customs} />
          </Group>
        ),
      },
      {
        id: "requested",
        header: () => (
          <span className={bookingTable.headerCell}>Requested cargo</span>
        ),
        cell: ({ row }) => (
          <RequestedCargoChips lines={row.original.requested} size="sm" />
        ),
      },
      {
        id: "created",
        header: () => <span className={bookingTable.headerCell}>Created</span>,
        cell: ({ row }) => (
          <Group gap={6} wrap="nowrap">
            <Calendar size={13} className="shrink-0 text-muted-foreground" />
            <Text size="sm" c="dimmed">
              {formatDate(row.original.createdAt)}
            </Text>
          </Group>
        ),
      },
      {
        id: "status",
        header: () => <span className={bookingTable.headerCell}>Status</span>,
        cell: ({ row }) => (
          <Group gap={6} wrap="nowrap">
            <Badge
              variant="light"
              color={shipmentStatusColor(row.original.status)}
              radius="sm"
            >
              {prettyStatus(row.original.status)}
            </Badge>
            {row.original.bookingCreated ? (
              <Tooltip label="Booking created by GL Ethiopia" withArrow>
                <Badge
                  variant="light"
                  color="blue"
                  radius="sm"
                  leftSection={<PackagePlus size={11} />}
                >
                  Booked
                </Badge>
              </Tooltip>
            ) : null}
          </Group>
        ),
      },
      {
        id: "actions",
        header: "",
        size: 200,
        cell: ({ row }) => {
          const r = row.original;
          const bookable = isBookable(r);
          const rebookable = isRebookable(r);
          return (
            <Group
              justify="flex-end"
              gap={6}
              pr="xs"
              wrap="nowrap"
              onClick={(e) => e.stopPropagation()}
            >
              {bookable ? (
                <Button
                  size="compact-sm"
                  color="edr-green"
                  radius="md"
                  leftSection={<PackagePlus size={14} />}
                  onClick={() => onCreateBooking(r)}
                >
                  Create booking
                </Button>
              ) : null}
              {rebookable ? (
                <Button
                  size="compact-sm"
                  color="grape"
                  radius="md"
                  leftSection={<RefreshCw size={14} />}
                  onClick={() => onRebook(r)}
                >
                  Rebook
                </Button>
              ) : null}
              <Menu shadow="md" radius="md" position="bottom-end" withinPortal>
                <Menu.Target>
                  <ActionIcon
                    variant="subtle"
                    color="gray"
                    radius="md"
                    aria-label="Row actions"
                  >
                    <MoreHorizontal size={16} />
                  </ActionIcon>
                </Menu.Target>
                <Menu.Dropdown>
                  <Menu.Item leftSection={<Eye size={14} />} onClick={() => onOpen(r.id)}>
                    Open booking
                  </Menu.Item>
                  {bookable ? (
                    <Menu.Item
                      leftSection={<PackagePlus size={14} />}
                      onClick={() => onCreateBooking(r)}
                    >
                      Create booking
                    </Menu.Item>
                  ) : null}
                  {rebookable ? (
                    <Menu.Item
                      leftSection={<RefreshCw size={14} />}
                      onClick={() => onRebook(r)}
                    >
                      Rebook (GL)
                    </Menu.Item>
                  ) : null}
                  {r.contractId ? (
                    <Menu.Item
                      leftSection={<ExternalLink size={14} />}
                      onClick={() => onViewContract(r.contractId!)}
                    >
                      View contract
                    </Menu.Item>
                  ) : null}
                </Menu.Dropdown>
              </Menu>
            </Group>
          );
        },
      },
    ],
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [canCreateBooking, onOpen, onCreateBooking, onViewContract],
  );

  if (!loading && !error && rows.length === 0) {
    return (
      <Stack align="center" gap={8} py={48}>
        <ThemeIcon variant="light" color="gray" radius="xl" size={48}>
          <Inbox size={22} />
        </ThemeIcon>
        <Text c="dimmed">No shipment bookings in clearance.</Text>
      </Stack>
    );
  }

  return (
    <Box style={{ overflowX: "auto" }} px="xs" pb="xs">
      <DataTable<ShipmentBookingRow, unknown>
        columns={columns}
        data={rows}
        status={loading ? "loading" : error ? "error" : "success"}
        onRowClick={(row) => onOpen(row.id)}
        containerClassName="border-0 shadow-none bg-transparent"
      />
    </Box>
  );
}

function ClearanceCardGrid({
  rows,
  loading,
  onOpen,
}: {
  rows: ClearanceRow[];
  loading: boolean;
  onOpen: (id: string) => void;
}) {
  if (loading) {
    return (
      <Box px="md" py="xl">
        <Text c="dimmed" ta="center">
          Loading…
        </Text>
      </Box>
    );
  }
  if (rows.length === 0) {
    return (
      <Stack align="center" gap={8} py={48}>
        <ThemeIcon variant="light" color="gray" radius="xl" size={48}>
          <Inbox size={22} />
        </ThemeIcon>
        <Text c="dimmed">No contracts need customs clearance.</Text>
      </Stack>
    );
  }
  return (
    <Box
      px="md"
      pb="md"
      style={{
        display: "grid",
        gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
        gap: "var(--mantine-spacing-md)",
      }}
    >
      {rows.map((r) => (
        <ClearanceCard key={r.id} row={r} onOpen={() => onOpen(r.id)} />
      ))}
    </Box>
  );
}

function ClearanceCard({
  row,
  onOpen,
}: {
  row: ClearanceRow;
  onOpen: () => void;
}) {
  return (
    <Card
      withBorder
      shadow="sm"
      radius="lg"
      p="md"
      onClick={onOpen}
      role="button"
      tabIndex={0}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          onOpen();
        }
      }}
      style={{ cursor: "pointer", transition: "all 120ms ease" }}
      className="hover:border-edr-green-4 hover:shadow-md"
    >
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Group gap={10} wrap="nowrap" style={{ minWidth: 0 }}>
          <ThemeIcon variant="light" color="edr-green" radius="md" size={40}>
            <FileText size={19} />
          </ThemeIcon>
          <Box style={{ minWidth: 0 }}>
            <Text fw={700} size="sm" c="edr-text" truncate>
              {row.reference}
            </Text>
            <Group gap={4} wrap="nowrap">
              <User size={11} className="shrink-0 opacity-70" />
              <Text size="xs" c="dimmed" truncate>
                {row.customerLabel}
              </Text>
            </Group>
          </Box>
        </Group>
        <StatusBadge row={row} />
      </Group>

      <Box
        mt="md"
        p="sm"
        style={{
          borderRadius: 12,
          background: "var(--mantine-color-edr-card-6)",
          border: "1px solid var(--mantine-color-edr-border-6)",
        }}
      >
        <Group gap={8} wrap="nowrap" justify="center">
          <Text size="sm" fw={600} truncate maw={130}>
            {row.originLabel}
          </Text>
          <ArrowRight size={15} className="shrink-0 text-muted-foreground" />
          <Text size="sm" fw={600} truncate maw={130}>
            {row.destinationLabel}
          </Text>
        </Group>
      </Box>

      <Group justify="space-between" mt="md" wrap="nowrap">
        <Group gap={8} wrap="nowrap">
          <DirectionIcon direction={row.tradeDirection} />
          <Badge size="xs" variant="default" radius="sm">
            {row.freightType}
          </Badge>
        </Group>
        <Badge size="xs" variant="default" radius="sm" tt="uppercase">
          {row.contractKind === "GENERAL" ? "General" : "One-time"}
        </Badge>
      </Group>

      <Group justify="space-between" mt={8} wrap="nowrap" gap={8}>
        <Text size="xs" c="dimmed" truncate maw={150}>
          {row.serviceTypeName}
        </Text>
        <CustomsBadge customs={row.customs} />
      </Group>
    </Card>
  );
}
