import { useEffect, useMemo, useRef, useState } from "react";
import {
  useNavigate,
  useParams,
  useSearchParams,
} from "react-router-dom";
import { useMutation, useQuery } from "@tanstack/react-query";
import {
  Alert,
  Badge,
  Box,
  Button,
  Center,
  Divider,
  Group,
  Loader,
  Modal,
  NumberInput,
  Paper,
  Select,
  Stack,
  Switch,
  Text,
  Textarea,
  TextInput,
  ThemeIcon,
} from "@mantine/core";
import {
  AlertCircle,
  AlertTriangle,
  CalendarDays,
  CheckCircle2,
  ChevronLeft,
  FileText,
  MapPin,
  Package,
  Receipt,
  X,
} from "lucide-react";
import type { Freight } from "@edr/types";
import { OperationDatePicker } from "@edr/ui-common";

import { api } from "@/services/api";
import { PageContainer } from "@/components/page";
import { PageHeader } from "@/components/page/PageHeader";
import { contractsService } from "@/services/contracts.service";
import {
  useContractDetail,
  useContractMutations,
} from "@/hooks/contracts/useContracts";
import {
  computeGlShipmentTotal,
  formatRateUnit,
  type GlShipmentQuantities,
} from "./gl-booking-form/total";
import { ContractCapacityNotice } from "./gl-booking-form/ContractCapacityNotice";
import {
  fieldStyles,
  StepCard,
  StepHeader,
  StepLabel,
} from "./gl-booking-form/form-ui";

/** All booking-window times are communicated in East Africa Time. */
const EAT_TZ = "Africa/Addis_Ababa";

// ISO 6346: 4-letter owner/category code + 6-digit serial + check digit.
// Same rule the customer portal shipment form enforces.
const ISO_CONTAINER_NUMBER_REGEX = /^[A-Z]{4}\d{7}$/;

interface UnitErrors {
  containerNumber?: string;
  vgmTons?: string;
}

interface BulkErrors {
  quantity?: string;
  hazardous?: string;
  reefer?: string;
}

function fmtWindowOpensAt(iso: string): string {
  const date = new Date(iso).toLocaleDateString("en-GB", {
    weekday: "short",
    day: "numeric",
    month: "short",
    timeZone: EAT_TZ,
  });
  const time = new Date(iso).toLocaleTimeString("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
    timeZone: EAT_TZ,
  });
  return `${date} · ${time}`;
}

interface UnitDraft {
  containerNumber: string;
  sealNumber: string;
  vgmTons: number | string;
  /** Per-unit flags — the line's hazardous/reefer counts are derived from these. */
  hazardous: boolean;
  reefer: boolean;
}

interface ContainerLineDraft {
  containerSize: string;
  units: UnitDraft[];
}

interface BulkLineDraft {
  cargoTypeId: string;
  cargoWeightTons: number | string;
  itemCount: number | string;
  hazardousQuantity: number | string;
  reeferQuantity: number | string;
}

function emptyUnit(): UnitDraft {
  return {
    containerNumber: "",
    sealNumber: "",
    vgmTons: "",
    hazardous: false,
    reefer: false,
  };
}

function bulkUnitOfMeasure(
  contract: Freight.IContract,
): "PER_TON" | "PER_ITEM" {
  const hasPerItem = contract.pricingBreakdown?.lineItems?.some(
    (li) => li.unit === "per_item",
  );
  return hasPerItem ? "PER_ITEM" : "PER_TON";
}

export default function GlCreateBookingForm() {
  const { id } = useParams<{ id: string }>();
  const [searchParams] = useSearchParams();
  const requestId = searchParams.get("requestId");
  const navigate = useNavigate();
  const { data: contract, isLoading } = useContractDetail(id);
  const mutations = useContractMutations(id ?? "");

  const { data: bookingRequest } = useQuery({
    queryKey: ["shipment-request", requestId],
    queryFn: () => contractsService.getBookingRequest(requestId!),
    enabled: Boolean(requestId),
  });

  // Same window-gating the customer sees: GL may only create a booking while a
  // booking window is OPEN for one of the contract's routes.
  const contractId = contract?.id ?? id;
  const { data: bookingWindows, isLoading: windowsLoading } = useQuery({
    ...api.trainScheduling.contractBookingWindows.queryOptions({
      input: { contractId: contractId ?? "" },
    }),
    enabled: Boolean(contractId),
  });

  const windowOpen = useMemo(
    () => (bookingWindows ?? []).some((w) => w.isOpenNow),
    [bookingWindows],
  );

  // Next future window across all routes, used for the "next window" notice —
  // the train dispatching soonest among those not yet open, matching the
  // departure-date ordering of the window cards.
  const nextWindow = useMemo(() => {
    const now = Date.now();
    return (bookingWindows ?? [])
      .filter((w) => w.windowOpensAt && new Date(w.windowOpensAt).getTime() > now)
      .sort((a, b) => {
        const da = a.departureDate ? new Date(a.departureDate).getTime() : Infinity;
        const db = b.departureDate ? new Date(b.departureDate).getTime() : Infinity;
        if (da !== db) return da - db;
        return new Date(a.windowOpensAt!).getTime() - new Date(b.windowOpensAt!).getTime();
      })[0];
  }, [bookingWindows]);

  const [scheduledDate, setScheduledDate] = useState("");
  const [contractRouteId, setContractRouteId] = useState<string | null>(null);
  const [notes, setNotes] = useState("");
  const [containerLines, setContainerLines] = useState<ContainerLineDraft[]>([]);
  const [bulkLines, setBulkLines] = useState<BulkLineDraft[]>([]);
  const [prefilled, setPrefilled] = useState(false);
  const [priceOpen, setPriceOpen] = useState(false);
  const seededRef = useRef(false);

  const isContainer = contract?.freightType === "CONTAINER";
  const routes = useMemo(
    () =>
      [...(contract?.routes ?? [])].sort((a, b) => a.sortOrder - b.sortOrder),
    [contract?.routes],
  );
  const needsRouteSelect = contract?.contractKind === "GENERAL" && routes.length > 1;

  const containerSizes = useMemo(() => {
    const sizes = new Set<string>();
    (contract?.cargoScope ?? []).forEach((s) => {
      if (s.containerSize) sizes.add(s.containerSize);
    });
    return [...sizes];
  }, [contract?.cargoScope]);

  const bulkCargoOptions = useMemo(() => {
    const seen = new Map<string, string>();
    (contract?.cargoScope ?? []).forEach((s) => {
      if (s.containerSize || !s.cargoTypeId) return;
      if (!seen.has(s.cargoTypeId)) {
        seen.set(s.cargoTypeId, s.cargoFreeText?.trim() || s.cargoTypeId);
      }
    });
    return [...seen.entries()].map(([value, label]) => ({ value, label }));
  }, [contract?.cargoScope]);

  const defaultBulkCargoTypeId = bulkCargoOptions[0]?.value ?? "";

  useEffect(() => {
    if (!bookingRequest || prefilled) return;
    setPrefilled(true);
    const lines = bookingRequest.requestedLines ?? {};
    if (lines.containers?.length) {
      setContainerLines(
        lines.containers.map((c) => ({
          containerSize: c.containerSize,
          // The request carries counts; pre-toggle the first N units so GL sees
          // the customer's declared hazardous/reefer split and can adjust it.
          units: Array.from({ length: Math.max(1, c.quantity) }, (_, i) => ({
            ...emptyUnit(),
            hazardous: i < Number(c.hazardousQuantity ?? 0),
            reefer: i < Number(c.reeferQuantity ?? 0),
          })),
        })),
      );
    } else if (lines.bulk) {
      setBulkLines([
        {
          cargoTypeId: lines.bulk.cargoTypeId ?? defaultBulkCargoTypeId,
          cargoWeightTons: lines.bulk.cargoWeightTons ?? "",
          itemCount: lines.bulk.itemCount ?? "",
          hazardousQuantity: lines.bulk.hazardousQuantity ?? "0",
          reeferQuantity: "",
        },
      ]);
    }
    if (bookingRequest.contractRouteId)
      setContractRouteId(bookingRequest.contractRouteId);
    if (bookingRequest.notes) setNotes(bookingRequest.notes);
  }, [bookingRequest, prefilled, defaultBulkCargoTypeId]);

  useEffect(() => {
    if (!contract || prefilled || seededRef.current) return;
    seededRef.current = true;
    if (isContainer && containerSizes.length > 0 && containerLines.length === 0) {
      setContainerLines(
        containerSizes.map((size) => ({
          containerSize: size,
          units: [emptyUnit()],
        })),
      );
    } else if (!isContainer && bulkLines.length === 0) {
      setBulkLines([
        {
          cargoTypeId: defaultBulkCargoTypeId,
          cargoWeightTons: "",
          itemCount: "",
          hazardousQuantity: "0",
          reeferQuantity: "0",
        },
      ]);
    }
  }, [
    contract,
    prefilled,
    isContainer,
    containerSizes,
    containerLines.length,
    bulkLines.length,
    defaultBulkCargoTypeId,
  ]);

  const quantities: GlShipmentQuantities = useMemo(
    () => ({
      isContainer: Boolean(isContainer),
      containers: containerLines.map((l) => ({
        containerSize: l.containerSize,
        quantity: l.units.length,
        hazardousQuantity: l.units.filter((u) => u.hazardous).length,
        reeferQuantity: l.units.filter((u) => u.reefer).length,
      })),
      bulkQuantity: bulkLines.reduce(
        (s, l) => s + Number(l.cargoWeightTons || l.itemCount || 0),
        0,
      ),
      bulkHazardousQuantity: bulkLines.reduce(
        (s, l) => s + Number(l.hazardousQuantity || 0),
        0,
      ),
    }),
    [isContainer, containerLines, bulkLines],
  );

  const priceTotal = useMemo(
    () => (contract ? computeGlShipmentTotal(contract, quantities) : null),
    [contract, quantities],
  );

  const selectedRoute = useMemo(
    () => routes.find((r) => r.id === contractRouteId) ?? routes[0],
    [routes, contractRouteId],
  );

  const cargoQuery = useMemo<Freight.AvailableDaysForCargoQuery | null>(() => {
    if (!selectedRoute?.originYardId || !selectedRoute?.destinationYardId)
      return null;
    if (isContainer) {
      const containers = containerLines
        .map((l) => ({
          containerSize: l.containerSize,
          quantity: l.units.length,
        }))
        .filter((c) => c.quantity >= 1);
      if (containers.length === 0) return null;
      return {
        originYardId: selectedRoute.originYardId,
        destinationYardId: selectedRoute.destinationYardId,
        freightType: "CONTAINER",
        containers,
      };
    }
    const tons = bulkLines.reduce(
      (s, l) => s + Number(l.cargoWeightTons || 0),
      0,
    );
    if (tons <= 0) return null;
    return {
      originYardId: selectedRoute.originYardId,
      destinationYardId: selectedRoute.destinationYardId,
      freightType: "BULK",
      cargoTypeCode:
        contract?.pricingBreakdown?.lineItems?.find((li) => li.cargoTypeCode)
          ?.cargoTypeCode ?? undefined,
      totalWeightTons: tons,
    };
  }, [selectedRoute, isContainer, containerLines, bulkLines, contract?.pricingBreakdown]);

  const { data: availableDays, isLoading: daysLoading } = useQuery({
    ...api.trainScheduling.availableDaysForCargo.queryOptions({
      input: cargoQuery ?? { freightType: "BULK" as const },
    }),
    enabled: cargoQuery !== null,
  });

  const syncUnits = (lineIdx: number, qty: number) => {
    setContainerLines((prev) =>
      prev.map((line, i) => {
        if (i !== lineIdx) return line;
        const next = [...line.units];
        while (next.length < qty) next.push(emptyUnit());
        next.length = Math.max(0, qty);
        return { ...line, units: next };
      }),
    );
  };

  const patchLine = (idx: number, patch: Partial<ContainerLineDraft>) =>
    setContainerLines((prev) =>
      prev.map((l, i) => (i === idx ? { ...l, ...patch } : l)),
    );

  const patchUnit = (
    lineIdx: number,
    unitIdx: number,
    patch: Partial<UnitDraft>,
  ) =>
    patchLine(lineIdx, {
      units: containerLines[lineIdx].units.map((u, i) =>
        i === unitIdx ? { ...u, ...patch } : u,
      ),
    });

  const patchBulk = (idx: number, patch: Partial<BulkLineDraft>) =>
    setBulkLines((prev) =>
      prev.map((l, i) => (i === idx ? { ...l, ...patch } : l)),
    );

  // Same client-side validation as the customer portal shipment form: ISO
  // container numbers (unique within the shipment) and a positive VGM per unit;
  // bulk needs a positive quantity with hazardous/reefer portions bounded by it.
  const [showErrors, setShowErrors] = useState(false);

  const unitErrors = useMemo<UnitErrors[][]>(() => {
    if (!isContainer) return [];
    const numberCounts = new Map<string, number>();
    containerLines.forEach((line) =>
      line.units.forEach((u) => {
        const key = u.containerNumber.trim().toUpperCase();
        if (!key) return;
        numberCounts.set(key, (numberCounts.get(key) ?? 0) + 1);
      }),
    );
    return containerLines.map((line) =>
      line.units.map((u) => {
        const errs: UnitErrors = {};
        const key = u.containerNumber.trim().toUpperCase();
        if (!key) {
          errs.containerNumber = "Container number is required.";
        } else if (!ISO_CONTAINER_NUMBER_REGEX.test(key)) {
          errs.containerNumber =
            "Enter a valid ISO container number (e.g. ABCD1234567).";
        } else if ((numberCounts.get(key) ?? 0) > 1) {
          errs.containerNumber = "Duplicate container number in this shipment.";
        }
        const vgm = Number(u.vgmTons);
        if (String(u.vgmTons).trim() === "" || Number.isNaN(vgm) || vgm <= 0) {
          errs.vgmTons = "Enter a valid VGM.";
        }
        return errs;
      }),
    );
  }, [isContainer, containerLines]);

  const bulkErrors = useMemo<BulkErrors[]>(() => {
    if (isContainer) return [];
    return bulkLines.map((line) => {
      const errs: BulkErrors = {};
      const qty = Number(line.cargoWeightTons || line.itemCount || 0);
      if (Number.isNaN(qty) || qty <= 0) {
        errs.quantity = "Enter a quantity greater than 0.";
      }
      const h = Number(line.hazardousQuantity || 0);
      if (Number.isNaN(h) || h < 0) {
        errs.hazardous = "Enter a valid hazardous quantity.";
      } else if (qty > 0 && h > qty) {
        errs.hazardous = `Can't exceed the cargo quantity (${qty}).`;
      }
      const r = Number(line.reeferQuantity || 0);
      if (Number.isNaN(r) || r < 0) {
        errs.reefer = "Enter a valid refrigerated quantity.";
      } else if (qty > 0 && r > qty) {
        errs.reefer = `Can't exceed the cargo quantity (${qty}).`;
      }
      return errs;
    });
  }, [isContainer, bulkLines]);

  const cargoValid = isContainer
    ? unitErrors.every((line) =>
        line.every((e) => !e.containerNumber && !e.vgmTons),
      )
    : bulkErrors.every((e) => !e.quantity && !e.hazardous && !e.reefer);

  const canSubmit =
    windowOpen &&
    Boolean(scheduledDate) &&
    (!needsRouteSelect || Boolean(contractRouteId)) &&
    (isContainer ? containerLines.some((l) => l.units.length > 0) : bulkLines.length > 0);

  /** The create-booking DTO from the current form state — shared by the
   * authoritative price preview and the actual submit so what GL confirms is
   * exactly what gets booked. */
  const buildPayload = (): Freight.CreateBookingUnderContractDto | null => {
    if (!scheduledDate || !contract) return null;

    const payload: Freight.CreateBookingUnderContractDto = {
      scheduledDate,
      ...(contractRouteId ? { contractRouteId } : {}),
      ...(notes.trim() ? { notes: notes.trim() } : {}),
    };

    if (isContainer) {
      payload.containers = containerLines
        .filter((l) => l.units.length > 0)
        .map((l) => ({
          containerSize: l.containerSize,
          quantity: l.units.length,
          // Counts are derived from the per-unit toggles — they can never
          // exceed the line quantity.
          hazardousQuantity: l.units.filter((u) => u.hazardous).length,
          reeferQuantity: l.units.filter((u) => u.reefer).length,
          units: l.units.map((u) => ({
            containerNumber: u.containerNumber.trim().toUpperCase(),
            ...(u.sealNumber ? { sealNumber: u.sealNumber } : {}),
            vgmTons: Number(u.vgmTons) || 0,
          })),
        }));
    } else {
      payload.bulkLines = bulkLines.map((l) => ({
        ...(l.cargoTypeId ? { cargoTypeId: l.cargoTypeId } : {}),
        ...(l.cargoWeightTons !== ""
          ? { cargoWeightTons: Number(l.cargoWeightTons) }
          : {}),
        ...(l.itemCount !== "" ? { itemCount: Number(l.itemCount) } : {}),
        ...(l.hazardousQuantity !== ""
          ? { hazardousQuantity: Number(l.hazardousQuantity) }
          : {}),
        ...(l.reeferQuantity !== ""
          ? { reeferQuantity: Number(l.reeferQuantity) }
          : {}),
      }));
    }

    return payload;
  };

  // Authoritative price preview (same pricing pass the booking persists at
  // create): rail freight + first/last mile + overweight + every surcharge.
  // Fired when the price modal opens; the modal falls back to the contract
  // unit-rate estimate while it loads.
  const validateShipmentMutation = useMutation({
    mutationFn: (dto: Freight.CreateBookingUnderContractDto) =>
      contractsService.validateShipment(id ?? "", dto),
  });
  const validation = validateShipmentMutation.data ?? null;

  const serverTotal = useMemo(() => {
    const items = validation?.lineItems;
    if (!items?.length) return null;
    return {
      currency: validation?.currency ?? priceTotal?.currency ?? "ETB",
      lines: items.map((li) => ({
        label: li.description,
        unitPrice: li.unitAmount,
        unit: li.unit.toLowerCase(),
        quantity: li.quantity,
        amount: li.amount,
      })),
      total:
        validation?.totalAmount ?? items.reduce((s, l) => s + l.amount, 0),
    };
  }, [validation, priceTotal]);

  const displayTotal = serverTotal ?? priceTotal;
  const pairingErrors = validation?.pairingErrors ?? [];
  const capacityErrors = validation?.capacityErrors ?? [];
  const overweightLines = validation?.overweightLines ?? [];

  const openPriceModal = () => {
    // Surface the per-field errors (portal-parity validation) instead of
    // sending an invalid payload to the price preview.
    if (!cargoValid) {
      setShowErrors(true);
      return;
    }
    setShowErrors(false);
    setPriceOpen(true);
    const payload = buildPayload();
    if (payload) {
      validateShipmentMutation.reset();
      validateShipmentMutation.mutate(payload);
    }
  };

  const handleSubmit = () => {
    if (!contract || !windowOpen || !cargoValid) return;
    // Never book past unresolved 20ft pairing hard-blocks.
    if (pairingErrors.length > 0) return;
    // A line above the container type's max capacity can never book.
    if (capacityErrors.length > 0) return;
    const payload = buildPayload();
    if (!payload) return;

    mutations.createBooking.mutate(payload, {
      onSuccess: async (booking) => {
        if (requestId) {
          try {
            await contractsService.acceptBookingRequest(requestId, booking.id);
          } catch {
            // Non-fatal
          }
        }
        if (contract.contractKind === "GENERAL") {
          // GENERAL per-booking clearance: land on the booking's clearance
          // detail — the same page the Shipments tab on the hub opens.
          navigate(`/dashboard/clearance/${booking.id}`);
        } else {
          // ONE_TIME customs keeps its clearance on the contract.
          navigate(`/dashboard/contracts/clearance/${contract.id}`);
        }
      },
    });
  };

  if (isLoading) {
    return (
      <PageContainer>
        <Center mih="50vh">
          <Loader color="edr-green" />
        </Center>
      </PageContainer>
    );
  }

  if (!contract) {
    return (
      <PageContainer>
        <PageHeader
          title="Contract not found"
          backTo="/dashboard/contracts/clearance"
        />
      </PageContainer>
    );
  }

  const bulkUom = bulkUnitOfMeasure(contract);

  return (
    <PageContainer>
      <Group justify="space-between" align="flex-end" wrap="wrap" gap="md" mb="lg">
        <Box>
          <Text fw={800} fz={26} style={{ letterSpacing: "-0.01em" }}>
            New Shipment Booking
          </Text>
          <Text size="sm" c="dimmed" mt={4}>
            Book a shipment on behalf of the customer for contract {contract.reference}.
          </Text>
        </Box>
        <Button
          variant="default"
          radius="md"
          leftSection={<ChevronLeft size={16} />}
          onClick={() =>
            navigate(`/dashboard/contracts/clearance/${contract.id}`)
          }
        >
          Back to clearance
        </Button>
      </Group>

      {bookingRequest ? (
        <Alert
          color="edr-green"
          variant="light"
          radius="md"
          icon={<FileText size={16} />}
          title="From shipment request"
          mb="lg"
        >
          Booking on behalf of the customer for request{" "}
          <b>{bookingRequest.reference}</b>.
          {bookingRequest.scheduledDate ? (
            <>
              {" "}
              Customer requested{" "}
              <b>
                {new Intl.DateTimeFormat("en-GB", {
                  day: "2-digit",
                  month: "short",
                  year: "numeric",
                }).format(new Date(bookingRequest.scheduledDate))}
              </b>{" "}
              — set the binding shipment date below.
            </>
          ) : null}
        </Alert>
      ) : null}

      {!windowsLoading && !windowOpen ? (
        <Alert
          color="orange"
          variant="light"
          radius="md"
          icon={<AlertCircle size={16} />}
          title="Booking window is closed"
          mb="lg"
        >
          GL can create a booking only while a window is open.{" "}
          {nextWindow?.windowOpensAt ? (
            <>
              Next window: <b>{fmtWindowOpensAt(nextWindow.windowOpensAt)} EAT</b>{" "}
              for{" "}
              <b>
                {nextWindow.origin ?? "Origin"} → {nextWindow.destination ?? "Destination"}
              </b>
              .
            </>
          ) : (
            <>No upcoming booking window scheduled.</>
          )}
        </Alert>
      ) : null}

      {windowsLoading || windowOpen ? (
        <>
      <Stack gap="lg" maw={896} mx="auto">
        <StepCard>
          <StepHeader
            icon={<MapPin size={22} />}
            title="Route"
            description={
              needsRouteSelect
                ? "Choose which contracted route this shipment ships on."
                : "This shipment ships on the contract's only route."
            }
          />
          {needsRouteSelect ? (
            <Select
              label="Contract route *"
              placeholder="Select a route..."
              value={contractRouteId}
              onChange={setContractRouteId}
              data={routes.map((r) => ({
                value: r.id,
                label: `${r.originYard?.label ?? r.originYard?.code ?? "Origin"} → ${
                  r.destinationYard?.label ??
                  r.destinationYard?.code ??
                  "Destination"
                }`,
              }))}
              required
              radius={10}
              styles={fieldStyles}
            />
          ) : (
            <Paper withBorder radius="md" p="md" style={{ borderColor: "#E6ECF2" }}>
              <Text fz={14} fw={600}>
                {selectedRoute?.originYard?.label ??
                  selectedRoute?.originYard?.code ??
                  "—"}{" "}
                →{" "}
                {selectedRoute?.destinationYard?.label ??
                  selectedRoute?.destinationYard?.code ??
                  "—"}
              </Text>
              <Text fz={12} c="dimmed" mt={2}>
                {contract.tradeDirection}
              </Text>
            </Paper>
          )}
        </StepCard>

        {isContainer ? (
          <StepCard>
            <StepHeader
              icon={<Package size={22} />}
              title="Cargo Details"
              description="Enter the quantity and per-container details for each size in the contract scope."
            />
            <Stack gap={18}>
              <ContractCapacityNotice contractId={contract.id} isContainer />
              {containerLines.length === 0 ? (
                <Text fz="sm" c="dimmed">
                  This contract has no container sizes in scope.
                </Text>
              ) : (
                containerLines.map((line, lineIdx) => (
                  <Box
                    key={`${line.containerSize}-${lineIdx}`}
                    className="rounded-xl"
                    style={{ border: "1px solid #E6ECF2", padding: 16 }}
                  >
                    <Text fz={14} fw={700} mb={10}>
                      {line.containerSize} containers
                    </Text>
                    <Group gap={12} mb={12} align="flex-start">
                      <NumberInput
                        label="Quantity *"
                        min={1}
                        value={line.units.length}
                        onChange={(v) => syncUnits(lineIdx, Number(v) || 0)}
                        radius={10}
                        styles={fieldStyles}
                        w={160}
                      />
                      {contract.isHazardous ? (
                        <Badge variant="light" color="red" radius="sm" mt={30}>
                          {line.units.filter((u) => u.hazardous).length} hazardous
                        </Badge>
                      ) : null}
                      {contract.isReefer ? (
                        <Badge variant="light" color="blue" radius="sm" mt={30}>
                          {line.units.filter((u) => u.reefer).length} refrigerated
                        </Badge>
                      ) : null}
                    </Group>

                    <StepLabel>Per-container details</StepLabel>
                    <Stack gap={10} mt={8}>
                      {line.units.map((unit, unitIdx) => (
                        <Group key={unitIdx} gap={10} align="flex-start" wrap="nowrap">
                          <TextInput
                            label={unitIdx === 0 ? "Container number *" : undefined}
                            placeholder="e.g. MSCU1234567"
                            value={unit.containerNumber}
                            error={
                              showErrors
                                ? unitErrors[lineIdx]?.[unitIdx]?.containerNumber
                                : undefined
                            }
                            onChange={(e) =>
                              patchUnit(lineIdx, unitIdx, {
                                containerNumber: e.currentTarget.value,
                              })
                            }
                            radius={10}
                            styles={fieldStyles}
                            style={{ flex: 1 }}
                          />
                          <TextInput
                            label={unitIdx === 0 ? "Seal number" : undefined}
                            placeholder="Optional"
                            value={unit.sealNumber}
                            onChange={(e) =>
                              patchUnit(lineIdx, unitIdx, {
                                sealNumber: e.currentTarget.value,
                              })
                            }
                            radius={10}
                            styles={fieldStyles}
                            style={{ flex: 1 }}
                          />
                          <NumberInput
                            label={unitIdx === 0 ? "VGM (tons) *" : undefined}
                            placeholder="e.g. 24.5"
                            min={0}
                            decimalScale={2}
                            value={unit.vgmTons}
                            error={
                              showErrors
                                ? unitErrors[lineIdx]?.[unitIdx]?.vgmTons
                                : undefined
                            }
                            onChange={(v) =>
                              patchUnit(lineIdx, unitIdx, { vgmTons: v })
                            }
                            radius={10}
                            styles={fieldStyles}
                            style={{ flex: 1 }}
                          />
                          {/* Per-unit flags: toggle exactly the containers that are
                              hazardous / refrigerated; line counts derive from these. */}
                          {contract.isHazardous ? (
                            <Stack gap={6} align="center" style={{ flexShrink: 0 }}>
                              {unitIdx === 0 ? (
                                <Text fz={12} fw={600} c="#4A5A68">
                                  Hazardous
                                </Text>
                              ) : null}
                              <Switch
                                color="red"
                                size="sm"
                                mt={unitIdx === 0 ? 0 : 8}
                                aria-label={`Container ${unitIdx + 1} hazardous`}
                                checked={unit.hazardous}
                                onChange={(e) =>
                                  patchUnit(lineIdx, unitIdx, {
                                    hazardous: e.currentTarget.checked,
                                  })
                                }
                              />
                            </Stack>
                          ) : null}
                          {contract.isReefer ? (
                            <Stack gap={6} align="center" style={{ flexShrink: 0 }}>
                              {unitIdx === 0 ? (
                                <Text fz={12} fw={600} c="#4A5A68">
                                  Reefer
                                </Text>
                              ) : null}
                              <Switch
                                color="blue"
                                size="sm"
                                mt={unitIdx === 0 ? 0 : 8}
                                aria-label={`Container ${unitIdx + 1} refrigerated`}
                                checked={unit.reefer}
                                onChange={(e) =>
                                  patchUnit(lineIdx, unitIdx, {
                                    reefer: e.currentTarget.checked,
                                  })
                                }
                              />
                            </Stack>
                          ) : null}
                        </Group>
                      ))}
                    </Stack>
                  </Box>
                ))
              )}
            </Stack>
          </StepCard>
        ) : (
          <StepCard>
            <StepHeader
              icon={<Package size={22} />}
              title="Cargo Details"
              description="Enter the amount you are shipping for this booking."
            />
            <Stack gap={14}>
              <ContractCapacityNotice contractId={contract.id} isContainer={false} />
              {bulkLines.map((line, idx) => (
                <Stack key={idx} gap={14}>
                  {bulkCargoOptions.length > 0 ? (
                    <Select
                      label="Cargo type"
                      placeholder="Select cargo type"
                      value={line.cargoTypeId || null}
                      onChange={(v) => patchBulk(idx, { cargoTypeId: v ?? "" })}
                      data={bulkCargoOptions}
                      radius={10}
                      styles={fieldStyles}
                    />
                  ) : null}
                  {bulkUom === "PER_TON" ? (
                    <NumberInput
                      label="Quantity (tons) *"
                      placeholder="e.g. 1200"
                      min={0}
                      decimalScale={2}
                      value={line.cargoWeightTons}
                      error={showErrors ? bulkErrors[idx]?.quantity : undefined}
                      onChange={(v) => patchBulk(idx, { cargoWeightTons: v })}
                      radius={10}
                      styles={fieldStyles}
                    />
                  ) : (
                    <NumberInput
                      label="Item count *"
                      placeholder="e.g. 500"
                      min={0}
                      value={line.itemCount}
                      error={showErrors ? bulkErrors[idx]?.quantity : undefined}
                      onChange={(v) => patchBulk(idx, { itemCount: v })}
                      radius={10}
                      styles={fieldStyles}
                    />
                  )}
                  {contract.isHazardous ? (
                    <NumberInput
                      label="Hazardous quantity"
                      min={0}
                      value={line.hazardousQuantity}
                      error={showErrors ? bulkErrors[idx]?.hazardous : undefined}
                      onChange={(v) => patchBulk(idx, { hazardousQuantity: v })}
                      radius={10}
                      styles={fieldStyles}
                    />
                  ) : null}
                  {contract.isReefer ? (
                    <NumberInput
                      label="Refrigerated quantity"
                      min={0}
                      value={line.reeferQuantity}
                      error={showErrors ? bulkErrors[idx]?.reefer : undefined}
                      onChange={(v) => patchBulk(idx, { reeferQuantity: v })}
                      radius={10}
                      styles={fieldStyles}
                    />
                  ) : null}
                </Stack>
              ))}
            </Stack>
          </StepCard>
        )}

        <StepCard>
          <StepHeader
            icon={<CalendarDays size={22} />}
            title="Schedule"
            description="Pick the binding shipment day. Only days with an open train that has enough matching wagons for the cargo can be selected."
          />
          {cargoQuery === null ? (
            <Alert
              color="yellow"
              variant="light"
              radius="md"
              icon={<AlertCircle size={16} />}
            >
              Enter your cargo details first — available shipment days depend on
              the wagons your cargo needs.
            </Alert>
          ) : (
            <Box>
              <StepLabel>Shipment day *</StepLabel>
              <Box mt={10} w="100%">
                <OperationDatePicker
                  fullWidth
                  availableDays={availableDays ?? []}
                  isLoading={daysLoading}
                  value={scheduledDate}
                  onChange={setScheduledDate}
                />
              </Box>
            </Box>
          )}
        </StepCard>

        <StepCard>
          <Textarea
            label="Additional notes"
            placeholder="Any special instructions for this shipment…"
            rows={3}
            radius="md"
            value={notes}
            onChange={(e) => setNotes(e.currentTarget.value)}
          />
        </StepCard>
      </Stack>

      <Box
        style={{
          position: "sticky",
          bottom: 0,
          zIndex: 20,
          borderTop: "1px solid var(--mantine-color-gray-3)",
          backgroundColor: "rgba(255,255,255,0.94)",
          backdropFilter: "blur(14px)",
          padding: "16px 0",
          marginTop: 24,
        }}
      >
        <Box maw={896} mx="auto">
          {showErrors && !cargoValid ? (
            <Alert
              color="red"
              variant="light"
              radius="md"
              icon={<AlertCircle size={16} />}
              mb="sm"
            >
              Fix the highlighted cargo fields before reviewing the price.
            </Alert>
          ) : null}
          <Group justify="flex-end">
            <Button
              variant="default"
              radius="md"
              onClick={() =>
                navigate(`/dashboard/contracts/clearance/${contract.id}`)
              }
            >
              Cancel
            </Button>
            <Button
              color="edr-green"
              radius="md"
              leftSection={<Receipt size={16} />}
              disabled={!canSubmit}
              onClick={openPriceModal}
            >
              Review price &amp; book
            </Button>
          </Group>
        </Box>
      </Box>

      <Modal
        opened={priceOpen}
        onClose={() => {
          if (!mutations.createBooking.isPending) setPriceOpen(false);
        }}
        centered
        radius="lg"
        size="lg"
        title={
          <Group gap={10}>
            <ThemeIcon variant="light" color="edr-green" radius="md" size={34}>
              <Receipt size={18} />
            </ThemeIcon>
            <Box>
              <Text fw={800} fz={16}>
                Confirm shipment price
              </Text>
              <Text fz="xs" c="dimmed">
                Booking on behalf of the customer for {contract.reference}.
              </Text>
            </Box>
          </Group>
        }
      >
        {displayTotal ? (
          <Stack gap="md">
            {validateShipmentMutation.isPending && (
              <Group gap={8} c="dimmed">
                <Loader size="xs" color="edr-green" />
                <Text fz="sm" c="dimmed">
                  Computing the final price breakdown and checking container
                  weights…
                </Text>
              </Group>
            )}

            {pairingErrors.length > 0 && (
              <Alert
                color="red"
                variant="light"
                radius="md"
                icon={<AlertCircle size={16} />}
                title="Cannot create booking — 20ft wagon pairing"
              >
                <Stack gap={6}>
                  {pairingErrors.map((msg, i) => (
                    <Text key={i} fz="sm" c="red.8">
                      {msg}
                    </Text>
                  ))}
                  <Text fz="xs" c="red.7" mt={2}>
                    Adjust the 20ft container weights or quantities so pairs
                    differ by no more than 10 tons.
                  </Text>
                </Stack>
              </Alert>
            )}

            {capacityErrors.length > 0 && (
              <Alert
                color="red"
                variant="light"
                radius="md"
                icon={<AlertCircle size={16} />}
                title="Cannot create booking — over maximum capacity"
              >
                <Stack gap={6}>
                  {capacityErrors.map((msg, i) => (
                    <Text key={i} fz="sm" c="red.8">
                      {msg}
                    </Text>
                  ))}
                  <Text fz="xs" c="red.7" mt={2}>
                    Reduce the cargo weight or split it across more containers
                    to book this shipment.
                  </Text>
                </Stack>
              </Alert>
            )}

            {overweightLines.length > 0 && (
              <Alert
                color="yellow"
                variant="light"
                radius="md"
                icon={<AlertTriangle size={16} />}
                title="Overweight containers"
              >
                <Stack gap={6}>
                  {overweightLines.map((line, i) => (
                    <Text key={i} fz="sm" c="#9A5B00">
                      {line.containerTypeCode}: {line.totalVgmTons}t exceeds
                      limit {line.maxAllowedTons}t (+{line.excessTons}t
                      overweight)
                    </Text>
                  ))}
                  <Text fz="xs" c="#9A5B00" mt={2}>
                    An overweight surcharge applies (included in the total
                    below).
                  </Text>
                </Stack>
              </Alert>
            )}

            <Paper withBorder radius={16} p="lg" style={{ borderColor: "#E6ECF2" }}>
              <Stack gap={10}>
                {displayTotal.lines.map((line, i) => (
                  <Group key={i} justify="space-between" wrap="nowrap" gap="sm">
                    <Box style={{ minWidth: 0 }}>
                      <Text fz="sm" fw={500}>
                        {line.label}
                      </Text>
                      <Text fz="xs" c="dimmed">
                        {line.quantity.toLocaleString()} ×{" "}
                        {line.unitPrice.toLocaleString()} {displayTotal.currency} ·{" "}
                        {formatRateUnit(line.unit)}
                      </Text>
                    </Box>
                    <Text fz="sm" fw={600} style={{ whiteSpace: "nowrap" }}>
                      {line.amount.toLocaleString()} {displayTotal.currency}
                    </Text>
                  </Group>
                ))}
                {displayTotal.lines.length === 0 && (
                  <Text fz="sm" c="dimmed">
                    No priced lines — check the cargo details.
                  </Text>
                )}
              </Stack>
              <Divider my="md" />
              <Group justify="space-between" align="flex-end">
                <Text
                  fz="xs"
                  fw={700}
                  tt="uppercase"
                  c="edr-green"
                  style={{ letterSpacing: "0.06em" }}
                >
                  Total
                </Text>
                <Text fw={800} fz={28}>
                  {displayTotal.total.toLocaleString()}{" "}
                  <Text span fz={16} fw={700} c="dimmed">
                    {displayTotal.currency}
                  </Text>
                </Text>
              </Group>
            </Paper>

            <Group justify="space-between" mt="xs">
              <Button
                variant="default"
                radius="md"
                leftSection={<X size={16} />}
                onClick={() => setPriceOpen(false)}
                disabled={mutations.createBooking.isPending}
              >
                Reject &amp; edit
              </Button>
              <Button
                color="edr-green"
                radius="md"
                leftSection={<CheckCircle2 size={16} />}
                loading={mutations.createBooking.isPending}
                disabled={
                  validateShipmentMutation.isPending ||
                  pairingErrors.length > 0 ||
                  capacityErrors.length > 0
                }
                onClick={handleSubmit}
              >
                Confirm &amp; book
              </Button>
            </Group>
          </Stack>
        ) : null}
      </Modal>
        </>
      ) : null}
    </PageContainer>
  );
}
