import { Fragment, useEffect, useMemo, useState, type MouseEvent } from 'react';
import {
  ActionIcon,
  Alert,
  Badge,
  Button,
  Checkbox,
  Group,
  Loader,
  Menu,
  Modal,
  NumberInput,
  ScrollArea,
  Select,
  Stack,
  Table,
  Tabs,
  Text,
  Textarea,
  TextInput,
  Tooltip,
} from '@mantine/core';
import {
  ArrowRightLeft,
  Check,
  ChevronDown,
  ChevronRight,
  ClipboardCheck,
  Eye,
  FileText,
  History,
  Info,
  Layers,
  MapPin,
  MoreHorizontal,
  PackageCheck,
  PackageOpen,
  PackageSearch,
  Send,
  Search,
  Train,
  Truck,
} from 'lucide-react';

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';

import { api } from '@/services/api';
import { QUERY_KEYS } from '@/constants/QUERY_KEYS';
import { useToast } from '@/hooks/use-toast';
import { useAllWarehouseYards, useAllWarehouseZones, useInventoryInquiry } from '@/hooks/useWarehouses';
import { firstMileService } from '@/services/first-mile.service';
import { warehouseService } from '@/services/warehouse.service';
import type {
  EligibleBooking,
  InventoryInquiryFilter,
  InventoryStatus,
  InventoryInquiryResult,
  ImportTrain,
  ImportTrainItem,
  ImportUnloadedItem,
  ReadyToLoadRow,
  ReceiveInventoryPayload,
  TruckEntrancePayload,
  Warehouse,
  WarehouseInventoryItem,
  WarehouseYard,
  WarehouseZone,
} from '@/types/warehouse';
import { InventoryStatusBadge } from './badges';
import { BookingSelect } from './BookingSelect';
import { DeliverInventoryModal } from './DeliverInventoryModal';
import { ContainerItemsModal } from './ContainerItemsModal';
import { FeePreviewModal } from './FeePreviewModal';
import { InspectionReportModal } from './InspectionReportModal';
import { InventoryDetailModal } from './InventoryDetailModal';
import { InventoryHistoryModal } from './InventoryHistoryModal';
import { InventoryWorkbench } from './InventoryWorkbench';
import { InventoryInquiryDetailModal } from './InventoryInquiryDetailModal';
import { MoveInventoryModal } from './MoveInventoryModal';
import { ReleaseOrderModal } from './ReleaseOrderModal';
import { StoreInventoryModal } from './StoreInventoryModal';
import { WarehouseInquiryTable } from './WarehouseInquiryTable';
import { extractDownloadErrorMessage, extractErrorMessage, formatDate, formatNumber, inventoryStatusOptions } from './options';
import { openPdfBlob } from './pdf';
import '@/components/overview/overview.css';

type ImportUnloadAssignment = { bookingId: string; warehouseId: string; yardId: string; zoneId: string };
type ImportUnloadAssignmentDraft = Partial<Omit<ImportUnloadAssignment, 'bookingId'>>;

interface ReceiveInventoryModalProps {
  opened: boolean;
  onClose: () => void;
  /** When supplied the modal locks to a single booking (legacy single-receive). */
  bookingId?: string;
  bookingLabel?: string;
  mode?: 'single' | 'bulk';
  direction?: WarehouseFlowDirection;
  onReceived?: () => void;
}

function GrnDocumentButton({ inventoryId, grnNumber }: { inventoryId: string; grnNumber?: string | null }) {
  const { toast } = useToast();
  const [loading, setLoading] = useState(false);

  const openDocument = async (event: MouseEvent<HTMLButtonElement>) => {
    event.stopPropagation();
    if (!grnNumber) {
      toast({ variant: 'destructive', title: 'GRN document unavailable', description: 'This item has no GRN number yet.' });
      return;
    }
    setLoading(true);
    const pdfWindow = window.open('', '_blank');
    try {
      const response = await warehouseService.downloadGrnDocument(inventoryId);
      const opened = openPdfBlob(response.data, `grn-${grnNumber}.pdf`, pdfWindow);
      toast({ title: opened ? 'GRN document opened' : 'GRN document downloaded' });
    } catch (error) {
      pdfWindow?.close();
      toast({ variant: 'destructive', title: 'GRN document failed', description: await extractDownloadErrorMessage(error) });
    } finally {
      setLoading(false);
    }
  };

  return (
    <Button
      size="compact-xs"
      variant="subtle"
      color="teal"
      leftSection={<FileText size={12} />}
      disabled={!grnNumber}
      loading={loading}
      onClick={openDocument}
    >
      {grnNumber ?? 'No GRN'}
    </Button>
  );
}

interface Location {
  warehouseId: string;
  yardId: string;
  zoneId: string;
}

interface TruckEntranceFormState {
  ownerName: string;
  consigneeDetails: string;
  edrDigitalBookingId: string;
  tin: string;
  customerPhone: string;
  truckPlateNumber: string;
  trailerPlateNumber: string;
  assignedEquipmentNumber: string;
  customsSealNumber: string;
  declarationNumber: string;
  itemDescription: string;
  packagingType: string;
  unitCount: number | '';
  grossWeightKg: number | '';
  weighingRequired: boolean | null;
  netWeightKg: number | '';
  volumeDimensions: string;
  conditionAtReceipt: string;
  damagedRejectedQuantity: number | '';
  driverName: string;
  driverPhone: string;
  driverLicenseNumber: string;
  truckType: string;
  entranceTareWeightKg: number | '';
  exitTareWeightKg: number | '';
  driverSignatoryName: string;
  warehouseManagerName: string;
}

interface LockedTruckEntranceFields {
  ownerName?: boolean;
  consigneeDetails?: boolean;
  tin?: boolean;
  edrDigitalBookingId?: boolean;
  customerPhone?: boolean;
  truckPlateNumber?: boolean;
  trailerPlateNumber?: boolean;
  assignedEquipmentNumber?: boolean;
  itemDescription?: boolean;
  packagingType?: boolean;
  unitCount?: boolean;
  grossWeightKg?: boolean;
  driverName?: boolean;
  driverPhone?: boolean;
  driverLicenseNumber?: boolean;
  truckType?: boolean;
}

type PackagingFreightType = 'CONTAINER' | 'BULK' | 'MIXED';

const emptyTruckEntrance = (): TruckEntranceFormState => ({
  ownerName: '',
  consigneeDetails: '',
  edrDigitalBookingId: '',
  tin: '',
  customerPhone: '',
  truckPlateNumber: '',
  trailerPlateNumber: '',
  assignedEquipmentNumber: '',
  customsSealNumber: '',
  declarationNumber: '',
  itemDescription: '',
  packagingType: '',
  unitCount: '',
  grossWeightKg: '',
  weighingRequired: null,
  netWeightKg: '',
  volumeDimensions: '',
  conditionAtReceipt: '',
  damagedRejectedQuantity: '',
  driverName: '',
  driverPhone: '',
  driverLicenseNumber: '',
  truckType: '',
  entranceTareWeightKg: '',
  exitTareWeightKg: '',
  driverSignatoryName: '',
  warehouseManagerName: '',
});

const toTruckEntrancePayload = (form: TruckEntranceFormState): TruckEntrancePayload => ({
  ownerName: form.ownerName.trim() || undefined,
  consigneeDetails: form.consigneeDetails.trim() || undefined,
  edrDigitalBookingId: form.edrDigitalBookingId.trim() || undefined,
  tin: form.tin.trim() || undefined,
  customerPhone: form.customerPhone.trim() || undefined,
  truckPlateNumber: form.truckPlateNumber.trim(),
  trailerPlateNumber: form.trailerPlateNumber.trim() || undefined,
  assignedEquipmentNumber: form.assignedEquipmentNumber.trim() || undefined,
  customsSealNumber: form.customsSealNumber.trim() || undefined,
  declarationNumber: form.declarationNumber.trim() || undefined,
  itemDescription: form.itemDescription.trim() || undefined,
  packagingType: form.packagingType.trim() || undefined,
  unitCount: form.unitCount === '' ? undefined : Number(form.unitCount),
  weighingRequired: form.weighingRequired ?? undefined,
  grossWeightKg: form.weighingRequired && form.grossWeightKg !== '' ? Number(form.grossWeightKg) : undefined,
  netWeightKg: form.netWeightKg === '' ? undefined : Number(form.netWeightKg),
  volumeDimensions: form.volumeDimensions.trim() || undefined,
  conditionAtReceipt: form.conditionAtReceipt.trim() || undefined,
  damagedRejectedQuantity: form.damagedRejectedQuantity === '' ? undefined : Number(form.damagedRejectedQuantity),
  driverName: form.driverName.trim(),
  driverPhone: form.driverPhone.trim(),
  driverLicenseNumber: form.driverLicenseNumber.trim() || undefined,
  truckType: form.truckType.trim() || undefined,
  entranceTareWeightKg:
    form.entranceTareWeightKg === ''
      ? undefined
      : Number(form.entranceTareWeightKg),
  exitTareWeightKg: form.weighingRequired && form.exitTareWeightKg !== '' ? Number(form.exitTareWeightKg) : undefined,
  driverSignatoryName: form.driverSignatoryName.trim() || undefined,
  warehouseManagerName: form.warehouseManagerName.trim() || undefined,
});




const SUB_STAGE_COLOR: Record<string, string> = {
  PENDING: 'gray',
  RECEIVED: 'blue',
  GRN: 'teal',
  ASSIGNED: 'indigo',
  LOADED: 'grape',
  LEFT: 'orange',
  DELIVERED: 'green',
};

/**
 * Expanded booking row: the booking's containers / bulk items with their
 * lifecycle stage. Shares the ['container-items', bookingId] cache with
 * ContainerItemsModal, so expanding after using the modal is instant.
 */
function BookingItemsExpansion({
  bookingId,
  colSpan,
  bulkFallback,
}: {
  bookingId: string | null;
  colSpan: number;
  bulkFallback?: string;
}) {
  const { data: items = [], isLoading } = useQuery({
    queryKey: ['container-items', bookingId],
    queryFn: () => warehouseService.getContainerItems(bookingId as string),
    enabled: Boolean(bookingId),
  });

  return (
    <Table.Tr>
      <Table.Td colSpan={colSpan} bg="var(--mantine-color-gray-0)">
        {isLoading ? (
          <Group justify="center" py="sm">
            <Loader size="xs" />
          </Group>
        ) : items.length === 0 ? (
          <Text size="xs" c="dimmed" py={6}>
            {bulkFallback ?? 'No container units recorded on this booking.'}
          </Text>
        ) : (
          <Table verticalSpacing={4} fz="xs" withTableBorder>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Container #</Table.Th>
                <Table.Th>Goods</Table.Th>
                <Table.Th>Stage</Table.Th>
                <Table.Th>Truck</Table.Th>
                <Table.Th>GRN</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {items.map((i) => (
                <Table.Tr key={i.containerNumber}>
                  <Table.Td>
                    <Text size="xs" fw={600}>{i.containerNumber}</Text>
                  </Table.Td>
                  <Table.Td>{i.goods ?? '—'}</Table.Td>
                  <Table.Td>
                    <Badge size="xs" variant="light" color={SUB_STAGE_COLOR[i.stage] ?? 'gray'}>
                      {i.stage}
                    </Badge>
                  </Table.Td>
                  <Table.Td>{i.truckPlate ?? '—'}</Table.Td>
                  <Table.Td>{i.grnNumber ?? '—'}</Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        )}
      </Table.Td>
    </Table.Tr>
  );
}

type ConfirmAction = { title: string; message: string; confirmLabel: string; run: () => void };

/** One-click bulk actions are irreversible — make the click deliberate. */
function ConfirmActionModal({
  action,
  onClose,
}: {
  action: ConfirmAction | null;
  onClose: () => void;
}) {
  return (
    <Modal opened={Boolean(action)} onClose={onClose} title={action?.title ?? ''} centered size="sm">
      <Stack gap="md">
        <Text size="sm">{action?.message}</Text>
        <Group justify="flex-end">
          <Button variant="default" onClick={onClose}>
            Cancel
          </Button>
          <Button
            onClick={() => {
              action?.run();
              onClose();
            }}
          >
            {action?.confirmLabel}
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

/** "3 skipped — Booking not PAID" instead of a bare count. */
const skippedSummary = (
  skippedCount: number,
  results: Array<{ reason?: string; message?: string }>,
): string | undefined => {
  if (!skippedCount) return undefined;
  const reason = results.find((x) => x.reason || x.message);
  return `${skippedCount} skipped${reason ? ` — ${reason.reason ?? reason.message}` : ''}`;
};

const commonNonEmptyValue = (values: Array<string | null | undefined>) => {
  const unique = [...new Set(values.map((value) => value?.trim()).filter(Boolean))] as string[];
  return unique.length === 1 ? unique[0] : '';
};

const truckEntranceFromBookings = (bookings: EligibleBooking[]): {
  form: TruckEntranceFormState;
  lockedFields: LockedTruckEntranceFields;
  packagingFreightType: PackagingFreightType;
} => {
  const ownerName = commonNonEmptyValue(bookings.map((booking) => booking.customer));
  const tin = commonNonEmptyValue(bookings.map((booking) => booking.customerTin));
  const customerPhone = commonNonEmptyValue(bookings.map((booking) => booking.customerPhone));
  const consigneeDetails = commonNonEmptyValue(bookings.map((booking) => booking.customer));
  const assignedEquipmentNumber = commonNonEmptyValue(
    bookings.map((booking) => booking.customerTruckContainerNumber || booking.containerNumber),
  );
  const itemDescription = commonNonEmptyValue(bookings.map((booking) => booking.cargoDescription ?? booking.cargo));
  const packagingType = commonNonEmptyValue(bookings.map((booking) => booking.containerPackagingType));
  const truckPlateNumber = commonNonEmptyValue(
    bookings.map((booking) => booking.firstMileTruckPlateNumber || booking.customerTruckPlateNumber),
  );
  const trailerPlateNumber = commonNonEmptyValue(bookings.map((booking) => booking.firstMileTrailerPlateNumber));
  const driverName = commonNonEmptyValue(
    bookings.map((booking) => booking.firstMileDriverName || booking.customerTruckDriverName),
  );
  const driverPhone = commonNonEmptyValue(bookings.map((booking) => booking.firstMileDriverPhone));
  const driverLicenseNumber = commonNonEmptyValue(bookings.map((booking) => booking.firstMileDriverLicenseNumber));
  const truckType = commonNonEmptyValue(
    bookings.map((booking) => booking.firstMileTruckType || booking.customerTruckType),
  );
  const customsSealNumber = commonNonEmptyValue(bookings.map((booking) => booking.sealNumbers));
  // Booking's declared cargo weight (tonnes) — the receive-time net until re-weighed.
  const bookingWeight = bookings.length === 1 ? Number(bookings[0]?.weight ?? '') : NaN;
  const netWeightKg: number | '' = Number.isFinite(bookingWeight) && bookingWeight > 0 ? bookingWeight : '';
  const edrDigitalBookingId =
    bookings.length === 1
      ? bookings[0]?.reference ?? bookings[0]?.id ?? ''
      : commonNonEmptyValue(bookings.map((booking) => booking.reference));
  const unitCount =
    bookings.length === 1 && bookings[0]?.containerQuantity != null
      ? Number(bookings[0].containerQuantity)
      : '';
  const freightTypes = [...new Set(bookings.map((booking) => booking.freightType).filter(Boolean))];
  const packagingFreightType =
    freightTypes.length === 1 && freightTypes[0] === 'CONTAINER'
      ? 'CONTAINER'
      : freightTypes.length === 1 && freightTypes[0] === 'BULK'
        ? 'BULK'
        : 'MIXED';

  return {
    form: {
      ...emptyTruckEntrance(),
      ownerName,
      consigneeDetails,
      tin,
      customerPhone,
      edrDigitalBookingId,
      assignedEquipmentNumber,
      customsSealNumber,
      itemDescription,
      packagingType,
      unitCount,
      netWeightKg,
      grossWeightKg: '',
      truckPlateNumber,
      trailerPlateNumber,
      driverName,
      driverPhone,
      driverLicenseNumber,
      truckType,
      driverSignatoryName: driverName,
    },
    lockedFields: {
      ownerName: Boolean(ownerName),
      consigneeDetails: Boolean(consigneeDetails),
      tin: Boolean(tin),
      edrDigitalBookingId: Boolean(edrDigitalBookingId),
      customerPhone: Boolean(customerPhone),
      assignedEquipmentNumber: Boolean(assignedEquipmentNumber),
      itemDescription: Boolean(itemDescription),
      packagingType: Boolean(packagingType),
      unitCount: unitCount !== '',
      grossWeightKg: false,
      truckPlateNumber: Boolean(truckPlateNumber),
      trailerPlateNumber: Boolean(trailerPlateNumber),
      driverName: Boolean(driverName),
      driverPhone: Boolean(driverPhone),
      driverLicenseNumber: Boolean(driverLicenseNumber),
      truckType: Boolean(truckType),
    },
    packagingFreightType,
  };
};

const BULK_PACKAGING_TYPE_OPTIONS = [
  { value: 'BAG', label: 'Bag' },
  { value: 'SACK', label: 'Sack' },
  { value: 'BALE', label: 'Bale' },
  { value: 'CARTON', label: 'Carton' },
  { value: 'CRATE', label: 'Crate' },
  { value: 'DRUM', label: 'Drum' },
  { value: 'BARREL', label: 'Barrel' },
  { value: 'PALLET', label: 'Pallet' },
  { value: 'LOOSE_BULK', label: 'Loose bulk' },
  { value: 'OTHER', label: 'Other' },
];

const CONTAINER_PACKAGING_TYPE_OPTIONS = [
  { value: 'CONTAINER_20FT', label: '20 ft container' },
  { value: 'CONTAINER_40FT', label: '40 ft container' },
  { value: 'CONTAINER_45FT', label: '45 ft container' },
  { value: 'REEFER_CONTAINER', label: 'Reefer container' },
  { value: 'TANK_CONTAINER', label: 'Tank container' },
  { value: 'FLAT_RACK_CONTAINER', label: 'Flat rack container' },
  { value: 'OPEN_TOP_CONTAINER', label: 'Open top container' },
  { value: 'OTHER_CONTAINER', label: 'Other container' },
];

const packagingOptionsFor = (freightType: PackagingFreightType) =>
  freightType === 'CONTAINER'
    ? CONTAINER_PACKAGING_TYPE_OPTIONS
    : freightType === 'BULK'
      ? BULK_PACKAGING_TYPE_OPTIONS
      : [...CONTAINER_PACKAGING_TYPE_OPTIONS, ...BULK_PACKAGING_TYPE_OPTIONS];

function TruckEntranceFields({
  value,
  onChange,
  lockedFields,
  packagingFreightType = 'MIXED',
  allowTruckWeighing = true,
}: {
  value: TruckEntranceFormState;
  onChange: (next: TruckEntranceFormState) => void;
  lockedFields?: LockedTruckEntranceFields;
  packagingFreightType?: PackagingFreightType;
  allowTruckWeighing?: boolean;
}) {
  const packagingOptions = packagingOptionsFor(packagingFreightType);
  const quantityLabel =
    packagingFreightType === 'CONTAINER'
      ? 'Container quantity'
      : packagingFreightType === 'BULK'
        ? 'Unit count'
        : 'Quantity';

  return (
    <Stack gap="sm">
      <Text size="sm" fw={600}>Customer and cargo ownership</Text>
      <Group grow>
        <TextInput
          label="Owner's name"
          value={value.ownerName}
          readOnly={lockedFields?.ownerName}
          onChange={(e) => onChange({ ...value, ownerName: e.currentTarget.value })}
        />
        <TextInput
          label="Consignee details"
          value={value.consigneeDetails}
          readOnly={lockedFields?.consigneeDetails}
          onChange={(e) => onChange({ ...value, consigneeDetails: e.currentTarget.value })}
        />
      </Group>
      <Group grow>
        <TextInput
          label="EDR digital booking ID"
          value={value.edrDigitalBookingId}
          readOnly={lockedFields?.edrDigitalBookingId}
          onChange={(e) => onChange({ ...value, edrDigitalBookingId: e.currentTarget.value })}
        />
        <TextInput
          label="TIN"
          value={value.tin}
          readOnly={lockedFields?.tin}
          onChange={(e) => onChange({ ...value, tin: e.currentTarget.value })}
        />
      </Group>
      <TextInput
        label="Customer phone"
        value={value.customerPhone}
        readOnly={lockedFields?.customerPhone}
        onChange={(e) => onChange({ ...value, customerPhone: e.currentTarget.value })}
      />

      <Text size="sm" fw={600} mt="xs">Transport and equipment tracking</Text>
      <Group grow>
        <TextInput
          label="Truck plate number"
          required
          value={value.truckPlateNumber}
          readOnly={lockedFields?.truckPlateNumber}
          onChange={(e) => onChange({ ...value, truckPlateNumber: e.currentTarget.value })}
        />
        <TextInput
          label="Trailer plate number"
          value={value.trailerPlateNumber}
          readOnly={lockedFields?.trailerPlateNumber}
          onChange={(e) => onChange({ ...value, trailerPlateNumber: e.currentTarget.value })}
        />
      </Group>
      <Group grow>
        <TextInput
          label="Assigned wagon / container number"
          value={value.assignedEquipmentNumber}
          readOnly={lockedFields?.assignedEquipmentNumber}
          onChange={(e) => onChange({ ...value, assignedEquipmentNumber: e.currentTarget.value })}
        />
        <TextInput
          label="Customs seal number"
          value={value.customsSealNumber}
          onChange={(e) => onChange({ ...value, customsSealNumber: e.currentTarget.value })}
        />
      </Group>
      <Group grow>
        <TextInput
          label="Driver name"
          required
          value={value.driverName}
          readOnly={lockedFields?.driverName}
          onChange={(e) => onChange({ ...value, driverName: e.currentTarget.value })}
        />
        <TextInput
          label="Driver phone"
          required
          value={value.driverPhone}
          readOnly={lockedFields?.driverPhone}
          onChange={(e) => onChange({ ...value, driverPhone: e.currentTarget.value })}
        />
      </Group>
      <Group grow>
        <TextInput
          label="Driver license number"
          value={value.driverLicenseNumber}
          readOnly={lockedFields?.driverLicenseNumber}
          onChange={(e) => onChange({ ...value, driverLicenseNumber: e.currentTarget.value })}
        />
        <TextInput
          label="Truck type"
          value={value.truckType}
          readOnly={lockedFields?.truckType}
          onChange={(e) => onChange({ ...value, truckType: e.currentTarget.value })}
        />
      </Group>
      {allowTruckWeighing ? (
        <>
          <Select
            label="Weighing"
            required
            data={[
              { value: 'YES', label: 'Yes' },
              { value: 'NO', label: 'No' },
            ]}
            value={value.weighingRequired == null ? null : value.weighingRequired ? 'YES' : 'NO'}
            onChange={(next) =>
              onChange({
                ...value,
                weighingRequired: next === 'YES' ? true : next === 'NO' ? false : null,
                grossWeightKg: next === 'YES' ? value.grossWeightKg : '',
                exitTareWeightKg: next === 'YES' ? value.exitTareWeightKg : '',
              })
            }
          />
          {value.weighingRequired && (
            <Group grow>
              <NumberInput
                label="Gross weight (t)"
                required
                min={0}
                value={value.grossWeightKg}
                onChange={(v) => onChange({ ...value, grossWeightKg: v === '' ? '' : Number(v) })}
              />
              <NumberInput
                label="Exit tare weight (t)"
                required
                min={0}
                value={value.exitTareWeightKg}
                onChange={(v) => onChange({ ...value, exitTareWeightKg: v === '' ? '' : Number(v) })}
              />
            </Group>
          )}
        </>
      ) : (
        <Alert icon={<Info size={16} />} color="green" variant="light">
          <Text size="sm">
            Truck weighing is not required for a received first-mile arrival. The GRN uses the booking weight.
          </Text>
        </Alert>
      )}

      <Text size="sm" fw={600} mt="xs">Customs and compliance</Text>
      <TextInput
        label="Declaration / Bill of Entry number"
        value={value.declarationNumber}
        onChange={(e) => onChange({ ...value, declarationNumber: e.currentTarget.value })}
      />

      <Text size="sm" fw={600} mt="xs">Physical cargo specifications</Text>
      <TextInput
        label="Item description"
        value={value.itemDescription}
        readOnly={lockedFields?.itemDescription}
        onChange={(e) => onChange({ ...value, itemDescription: e.currentTarget.value })}
      />
      <Group grow>
        <Select
          label="Packaging type"
          data={packagingOptions}
          clearable
          searchable
          readOnly={lockedFields?.packagingType}
          value={value.packagingType}
          onChange={(v) => onChange({ ...value, packagingType: v ?? '' })}
        />
        <NumberInput
          label={quantityLabel}
          min={0}
          value={value.unitCount}
          readOnly={lockedFields?.unitCount}
          onChange={(v) => onChange({ ...value, unitCount: v === '' ? '' : Number(v) })}
        />
      </Group>
      <NumberInput
        label="Net weight (t)"
        min={0}
        value={value.netWeightKg}
        onChange={(v) => onChange({ ...value, netWeightKg: v === '' ? '' : Number(v) })}
      />
      <TextInput
        label="Volume / dimensions"
        value={value.volumeDimensions}
        onChange={(e) => onChange({ ...value, volumeDimensions: e.currentTarget.value })}
      />

      <Text size="sm" fw={600} mt="xs">Quality and inspection</Text>
      <Group grow>
        <TextInput
          label="Condition at receipt"
          value={value.conditionAtReceipt}
          onChange={(e) => onChange({ ...value, conditionAtReceipt: e.currentTarget.value })}
        />
        <NumberInput
          label="Damaged / rejected quantity"
          min={0}
          value={value.damagedRejectedQuantity}
          onChange={(v) => onChange({ ...value, damagedRejectedQuantity: v === '' ? '' : Number(v) })}
        />
      </Group>
      <Group grow>
        <TextInput
          label="Driver signatory"
          value={value.driverSignatoryName}
          onChange={(e) => onChange({ ...value, driverSignatoryName: e.currentTarget.value })}
        />
        <TextInput
          label="EDR warehouse manager"
          value={value.warehouseManagerName}
          onChange={(e) => onChange({ ...value, warehouseManagerName: e.currentTarget.value })}
        />
      </Group>
    </Stack>
  );
}

/** Cascading Warehouse → Yard → Zone selectors (ACTIVE only). */
function LocationSelects({
  value,
  onChange,
  allowedYardTypes,
  allowedZoneTypes,
}: {
  value: Location;
  onChange: (next: Location) => void;
  /** When non-empty, only yards of these types are offered (matched to freight). */
  allowedYardTypes?: string[];
  /** When non-empty, only zones of these types are offered. */
  allowedZoneTypes?: string[];
}) {
  const warehousesQuery = useQuery(
    api.warehouses.list.queryOptions({ input: { filter: { status: 'ACTIVE' } } }),
  );
  const yardsQuery = useQuery(
    api.warehouses.listYards.queryOptions({
      input: { warehouseId: value.warehouseId ?? '' },
      enabled: Boolean(value.warehouseId),
    }),
  );
  const zonesQuery = useQuery(
    api.warehouses.listZones.queryOptions({
      input: { yardId: value.yardId ?? '' },
      enabled: Boolean(value.yardId),
    }),
  );

  const warehouseOptions = useMemo(
    () => (warehousesQuery.data ?? []).map((w) => ({ value: w.id, label: `${w.name} (${w.code})` })),
    [warehousesQuery.data],
  );
  const yardOptions = useMemo(
    () =>
      (yardsQuery.data ?? [])
        .filter((y) => y.status === 'ACTIVE')
        .filter((y) => !allowedYardTypes?.length || allowedYardTypes.includes((y as { type?: string }).type ?? ''))
        .map((y) => ({ value: y.id, label: `${y.name} (${y.code})` })),
    [yardsQuery.data, allowedYardTypes],
  );
  const zoneOptions = useMemo(
    () =>
      (zonesQuery.data ?? [])
        .filter((z) => z.status === 'ACTIVE')
        .filter((z) => !allowedZoneTypes?.length || allowedZoneTypes.includes((z as { type?: string }).type ?? ''))
        .map((z) => ({ value: z.id, label: `${z.name} (${z.code})` })),
    [zonesQuery.data, allowedZoneTypes],
  );

  return (
    <Group grow align="flex-end">
      <Select
        label="Warehouse"
        placeholder={warehousesQuery.isLoading ? 'Loading…' : 'Select warehouse'}
        required
        searchable
        data={warehouseOptions}
        value={value.warehouseId || null}
        onChange={(v) => onChange({ warehouseId: v ?? '', yardId: '', zoneId: '' })}
      />
      <Select
        label="Yard"
        placeholder={!value.warehouseId ? 'Select warehouse first' : 'Select yard'}
        required
        searchable
        disabled={!value.warehouseId}
        data={yardOptions}
        value={value.yardId || null}
        onChange={(v) => onChange({ ...value, yardId: v ?? '', zoneId: '' })}
      />
      <Select
        label="Zone"
        placeholder={!value.yardId ? 'Select yard first' : 'Select zone'}
        required
        searchable
        disabled={!value.yardId}
        data={zoneOptions}
        value={value.zoneId || null}
        onChange={(v) => onChange({ ...value, zoneId: v ?? '' })}
      />
    </Group>
  );
}

/** One tab: eligible PAID bookings for a direction, with bulk receive (+ export load). */
function EligibleTab({
  direction,
  location,
  enabled,
  onChanged,
  focusedBookingId,
  focusedBookingLabel,
}: {
  direction: 'IMPORT' | 'EXPORT';
  location: Location;
  enabled: boolean;
  onChanged?: () => void;
  focusedBookingId?: string;
  focusedBookingLabel?: string;
}) {
  const { toast } = useToast();
  const qc = useQueryClient();
  const { data: allRows = [], isLoading } = useQuery(
    api.warehouses.eligibleBookings.queryOptions({
      input: { direction },
      enabled,
    }),
  );
  const rows = useMemo(
    () =>
      allRows.filter(
        (r) =>
          r.direction === direction &&
          (!focusedBookingId || r.id === focusedBookingId),
      ),
    [allRows, direction, focusedBookingId],
  );
  const bulkReceive = useMutation(api.warehouses.bulkReceive.mutationOptions());
  const requestFirstMile = useMutation({
    mutationFn: (reference: string) => firstMileService.accept(reference),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
      void qc.invalidateQueries({ queryKey: QUERY_KEYS.FIRST_MILE.ROOT });
      toast({ title: 'First mile requested', description: 'Booking was added to the existing First Mile workflow.' });
    },
    onError: (error) => {
      toast({ variant: 'destructive', title: 'First mile request failed', description: extractErrorMessage(error) });
    },
  });
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [statusTab, setStatusTab] = useState('ALL');
  const [truckOpen, setTruckOpen] = useState(false);
  const [pendingReceiveIds, setPendingReceiveIds] = useState<string[]>([]);
  const [receivedAt, setReceivedAt] = useState<string | null>(null);
  const [truckForm, setTruckForm] = useState<TruckEntranceFormState>(emptyTruckEntrance());
  const [lockedTruckFields, setLockedTruckFields] = useState<LockedTruckEntranceFields>({});
  const [packagingFreightType, setPackagingFreightType] = useState<PackagingFreightType>('MIXED');

  const locationReady = Boolean(location.warehouseId && location.yardId && location.zoneId);
  const canReceiveBooking = (row: EligibleBooking) =>
    !(direction === 'EXPORT' && row.hasFirstMile && row.firstMileStatus !== 'RECEIVED_TO_PORT');
  const statusOptions = useMemo(() => {
    const base = [{ value: 'ALL', label: 'All bookings' }];
    if (direction === 'EXPORT') {
      return [
        ...base,
        { value: 'DIRECT', label: 'Direct truck' },
        { value: 'FIRST_MILE', label: 'First mile' },
        { value: 'FIRST_MILE_READY', label: 'First mile arrived' },
        { value: 'AWAITING_FIRST_MILE', label: 'Awaiting first mile' },
      ];
    }
    return [
      ...base,
      { value: 'READY_TO_RECEIVE', label: 'Ready to receive' },
      { value: 'PAID', label: 'Paid' },
    ];
  }, [direction]);
  const statusFilteredRows = useMemo(
    () =>
      rows.filter((row) => {
        switch (statusTab) {
          case 'DIRECT':
            return !row.hasFirstMile;
          case 'FIRST_MILE':
            return row.hasFirstMile;
          case 'FIRST_MILE_READY':
            return row.hasFirstMile && row.firstMileStatus === 'RECEIVED_TO_PORT';
          case 'AWAITING_FIRST_MILE':
            return row.hasFirstMile && row.firstMileStatus !== 'RECEIVED_TO_PORT';
          case 'READY_TO_RECEIVE':
            return canReceiveBooking(row);
          case 'PAID':
            return row.paymentStatus === 'PAID';
          default:
            return true;
        }
      }),
    [rows, statusTab],
  );
  const statusCounts = useMemo(
    () =>
      Object.fromEntries(
        statusOptions.map((option) => [
          option.value,
          rows.filter((row) => {
            switch (option.value) {
              case 'DIRECT':
                return !row.hasFirstMile;
              case 'FIRST_MILE':
                return row.hasFirstMile;
              case 'FIRST_MILE_READY':
                return row.hasFirstMile && row.firstMileStatus === 'RECEIVED_TO_PORT';
              case 'AWAITING_FIRST_MILE':
                return row.hasFirstMile && row.firstMileStatus !== 'RECEIVED_TO_PORT';
              case 'READY_TO_RECEIVE':
                return canReceiveBooking(row);
              case 'PAID':
                return row.paymentStatus === 'PAID';
              default:
                return true;
            }
          }).length,
        ]),
      ),
    [rows, statusOptions],
  );
  const selectableRows = statusFilteredRows.filter(canReceiveBooking);
  const allSelected = selectableRows.length > 0 && selected.size === selectableRows.length;
  const someSelected = selected.size > 0 && !allSelected;
  const pendingReceiveRows = useMemo(
    () =>
      pendingReceiveIds
        .map((id) => rows.find((item) => item.id === id))
        .filter(Boolean) as EligibleBooking[],
    [pendingReceiveIds, rows],
  );
  const pendingHasFirstMile = pendingReceiveRows.some((row) => row.hasFirstMile);
  const pendingUsesFirstMile =
    pendingReceiveRows.length > 0 && pendingReceiveRows.every((row) => row.hasFirstMile);

  const toggleAll = () =>
    setSelected(allSelected ? new Set() : new Set(selectableRows.map((r) => r.id)));
  const toggleOne = (id: string) =>
    setSelected((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });

  const receiveBookings = async (bookingIds: string[], truckEntrance?: TruckEntrancePayload) => {
    try {
      const r = await bulkReceive.mutateAsync({
        direction,
        ...location,
        bookingIds,
        ...(truckEntrance ? { truckEntrance } : {}),
      });
      toast({
        title: `${r.receivedCount} received at ${direction === 'EXPORT' ? 'facility' : 'warehouse'}`,
        description: r.results.find((item) => item.grnNumber)?.grnNumber ?? skippedSummary(r.skippedCount, r.results),
      });
      const firstGrn = r.results.find((item) => item.inventoryId && item.grnNumber);
      if (focusedBookingId && firstGrn?.inventoryId && firstGrn.grnNumber) {
        const pdfWindow = window.open('', '_blank');
        try {
          const response = await warehouseService.downloadGrnDocument(firstGrn.inventoryId);
          const opened = openPdfBlob(response.data, `grn-${firstGrn.grnNumber}.pdf`, pdfWindow);
          toast({ title: opened ? 'GRN document opened' : 'GRN document downloaded' });
        } catch (error) {
          pdfWindow?.close();
          toast({ variant: 'destructive', title: 'GRN document failed', description: await extractDownloadErrorMessage(error) });
        }
      }
      setSelected(new Set());
      setTruckOpen(false);
      setPendingReceiveIds([]);
      setReceivedAt(null);
      setLockedTruckFields({});
      setPackagingFreightType('MIXED');
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Receive failed', description: extractErrorMessage(error) });
    }
  };

  const openTruckReceive = (bookingIds: string[]) => {
    if (!locationReady) {
      toast({ variant: 'destructive', title: 'Select warehouse, yard and zone first' });
      return;
    }
    if (bookingIds.length === 0) {
      toast({ variant: 'destructive', title: 'Select at least one booking' });
      return;
    }
    const allowedIds = new Set(selectableRows.map((row) => row.id));
    const filteredIds = bookingIds.filter((id) => allowedIds.has(id));
    if (filteredIds.length === 0) {
      toast({ variant: 'destructive', title: 'No selected booking is ready to receive' });
      return;
    }
    const selectedRows = filteredIds
      .map((id) => rows.find((item) => item.id === id))
      .filter(Boolean) as EligibleBooking[];
    if (direction === 'IMPORT') {
      void receiveBookings(filteredIds);
      return;
    }
    const hasFirstMileRows = selectedRows.some((row) => row.hasFirstMile);
    const hasCustomerTruckRows = selectedRows.some((row) => !row.hasFirstMile);
    if (hasFirstMileRows && hasCustomerTruckRows) {
      toast({
        variant: 'destructive',
        title: 'Receive separately',
        description: 'First-mile arrivals and customer-truck arrivals use different truck evidence. Select one group at a time.',
      });
      return;
    }
    const { form, lockedFields, packagingFreightType: nextPackagingFreightType } = truckEntranceFromBookings(selectedRows);
    const totalContainerQuantity = selectedRows.reduce(
      (sum, row) => sum + Number(row.containerQuantity ?? 0),
      0,
    );
    const usesFirstMile = selectedRows.length > 0 && selectedRows.every((row) => row.hasFirstMile);
    const usesCustomerAssignedTruck =
      selectedRows.length > 0 &&
      selectedRows.every((row) => !row.hasFirstMile && Boolean(row.customerTruckAssignedAt));
    const normalizedForm =
      nextPackagingFreightType === 'CONTAINER' && totalContainerQuantity > 0
        ? {
            ...form,
            unitCount: totalContainerQuantity,
          }
        : {
            ...form,
          };
    setPendingReceiveIds(filteredIds);
    setReceivedAt(new Date().toISOString());
    setTruckForm(normalizedForm);
    setLockedTruckFields({
      ...lockedFields,
      unitCount: nextPackagingFreightType === 'CONTAINER' && totalContainerQuantity > 0,
      assignedEquipmentNumber: usesCustomerAssignedTruck
        ? lockedFields.assignedEquipmentNumber
        : lockedFields.assignedEquipmentNumber,
      truckPlateNumber: (usesFirstMile || usesCustomerAssignedTruck) && lockedFields.truckPlateNumber,
      trailerPlateNumber: usesFirstMile && lockedFields.trailerPlateNumber,
      driverName: (usesFirstMile || usesCustomerAssignedTruck) && lockedFields.driverName,
      driverPhone: usesFirstMile && lockedFields.driverPhone,
      driverLicenseNumber: usesFirstMile && lockedFields.driverLicenseNumber,
      truckType: (usesFirstMile || usesCustomerAssignedTruck) && lockedFields.truckType,
    });
    setPackagingFreightType(nextPackagingFreightType);
    setTruckOpen(true);
  };

  const receive = async () => {
    if (!truckForm.truckPlateNumber.trim() || !truckForm.driverName.trim() || !truckForm.driverPhone.trim()) {
      toast({ variant: 'destructive', title: 'Truck and driver information are required' });
      return;
    }
    if (!pendingUsesFirstMile && truckForm.weighingRequired == null) {
      toast({ variant: 'destructive', title: 'Select whether customer truck weighing is required' });
      return;
    }
    if (truckForm.weighingRequired && (truckForm.grossWeightKg === '' || truckForm.exitTareWeightKg === '')) {
      toast({ variant: 'destructive', title: 'Gross weight and exit tare weight are required when weighing is Yes' });
      return;
    }
    await receiveBookings(pendingReceiveIds, toTruckEntrancePayload(truckForm));
  };


  return (
    <Stack gap="sm" mt="sm">
      <Tabs value={statusTab} onChange={(v) => setStatusTab(v ?? 'ALL')}>
        <Tabs.List>
          {statusOptions.map((option) => (
            <Tabs.Tab key={option.value} value={option.value}>
              {option.label} ({statusCounts[option.value] ?? 0})
            </Tabs.Tab>
          ))}
        </Tabs.List>
      </Tabs>

      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          Selected: <b>{selected.size}</b> / {statusFilteredRows.length} eligible
        </Text>
        <Group gap="xs">
          <Button
            size="compact-sm"
            color={direction === 'EXPORT' ? 'edr-green' : undefined}
            variant={direction === 'EXPORT' ? 'filled' : 'default'}
            leftSection={direction === 'EXPORT' ? <Truck size={14} /> : undefined}
            disabled={!locationReady || selectableRows.length === 0}
            loading={bulkReceive.isPending}
            onClick={() => openTruckReceive(selected.size > 0 ? [...selected] : selectableRows.map((r) => r.id))}
          >
            {direction === 'EXPORT' ? 'Receive All for Loading' : 'Receive All to Warehouse'}
          </Button>
          <Button
            size="compact-sm"
            variant="default"
            disabled={!locationReady || selected.size === 0}
            loading={bulkReceive.isPending}
            onClick={() => openTruckReceive([...selected])}
          >
            {direction === 'EXPORT' ? 'Receive Selected for Loading' : 'Receive Selected'}
          </Button>
        </Group>
      </Group>

      {!locationReady && (
        <Alert icon={<Info size={16} />} color="orange" variant="light">
          <Text size="sm">Select a warehouse, yard and zone above before receiving.</Text>
        </Alert>
      )}

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : statusFilteredRows.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          {focusedBookingLabel
            ? `${focusedBookingLabel} is not eligible for warehouse receiving yet.`
            : `No eligible PAID ${direction.toLowerCase()} bookings to receive.`}
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1350}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                <Table.Th w={40}>
                  <Checkbox
                    aria-label="Select all"
                    checked={allSelected}
                    indeterminate={someSelected}
                    onChange={toggleAll}
                  />
                </Table.Th>
                <Table.Th>Booking Ref</Table.Th>
                <Table.Th>Customer Name</Table.Th>
                <Table.Th>Origin</Table.Th>
                <Table.Th>Destination</Table.Th>
                <Table.Th>Route</Table.Th>
                <Table.Th>Container / Cargo Items</Table.Th>
                <Table.Th>Cargo Type</Table.Th>
                <Table.Th>Weight</Table.Th>
                <Table.Th>Payment</Table.Th>
                <Table.Th>Current Status</Table.Th>
                <Table.Th>Inspection</Table.Th>
                {direction === 'EXPORT' && <Table.Th>First Mile</Table.Th>}
                <Table.Th ta="right">Actions</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {statusFilteredRows.map((r) => {
                const canReceive = canReceiveBooking(r);
                return (
                <Table.Tr key={r.id}>
                  <Table.Td>
                    <Checkbox
                      aria-label={`Select ${r.reference}`}
                      checked={selected.has(r.id)}
                      disabled={!canReceive}
                      onChange={() => toggleOne(r.id)}
                    />
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" fw={600}>
                      {r.reference}
                    </Text>
                  </Table.Td>
                  <Table.Td>{r.customer ?? '—'}</Table.Td>
                  <Table.Td>{r.origin ?? '—'}</Table.Td>
                  <Table.Td>{r.destination ?? '—'}</Table.Td>
                  <Table.Td>
                    {r.origin || r.destination ? `${r.origin ?? '?'} → ${r.destination ?? '?'}` : '—'}
                  </Table.Td>
                  <Table.Td>
                    <Stack gap={2}>
                      <Text size="sm">{r.containerNumber ?? r.cargoDescription ?? r.cargo ?? '—'}</Text>
                      <Text size="xs" c="dimmed">
                        {[
                          r.containerQuantity != null ? `${r.containerQuantity} unit(s)` : null,
                          r.containerPackagingType,
                        ].filter(Boolean).join(' / ') || 'Item details from booking'}
                      </Text>
                    </Stack>
                  </Table.Td>
                  <Table.Td>{r.cargo ?? '—'}</Table.Td>
                  <Table.Td>{formatNumber(Number(r.weight))}</Table.Td>
                  <Table.Td>
                    <Badge color="green" variant="light" size="sm">
                      {r.paymentStatus}
                    </Badge>
                  </Table.Td>
                  <Table.Td>
                    <Badge color="gray" variant="light" size="sm">
                      {r.status ?? '—'}
                    </Badge>
                  </Table.Td>
                  <Table.Td>—</Table.Td>
                  {direction === 'EXPORT' && (
                    <Table.Td>
                      {r.hasFirstMile ? (
                        <Stack gap={2}>
                          <Badge
                            color={r.firstMileStatus === 'RECEIVED_TO_PORT' ? 'green' : r.firstMileRequestId ? 'blue' : 'orange'}
                            variant="light"
                            size="sm"
                          >
                            {r.firstMileStatus ?? 'Request needed'}
                          </Badge>
                          <Text size="xs" c="dimmed">
                            {[r.firstMileTruckPlateNumber, r.firstMileTrailerPlateNumber].filter(Boolean).join(' / ') || 'Truck not assigned'}
                          </Text>
                        </Stack>
                      ) : (
                        <Badge color="gray" variant="light" size="sm">Direct arrival</Badge>
                      )}
                    </Table.Td>
                  )}
                  <Table.Td ta="right">
                    {direction === 'EXPORT' && r.hasFirstMile && !r.firstMileRequestId ? (
                      <Button
                        size="compact-xs"
                        variant="light"
                        color="orange"
                        loading={requestFirstMile.isPending}
                        onClick={() => requestFirstMile.mutate(r.reference)}
                      >
                        Request First Mile
                      </Button>
                    ) : (
                      <Button
                        size="compact-xs"
                        variant="light"
                        disabled={!locationReady || !canReceive}
                        loading={bulkReceive.isPending}
                        onClick={() => openTruckReceive([r.id])}
                      >
                        {canReceive ? (direction === 'EXPORT' ? 'Receive for Loading' : 'Receive to Warehouse') : 'Await First Mile'}
                      </Button>
                    )}
                  </Table.Td>
                </Table.Tr>
                );
              })}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}

      <Modal
        opened={truckOpen}
        onClose={() => setTruckOpen(false)}
        title={direction === 'EXPORT' ? 'Receive for Loading' : 'Receive to Warehouse'}
        centered
        size="lg"
      >
        <Stack gap="md">
          <Alert icon={<Truck size={16} />} color={pendingHasFirstMile ? 'green' : 'blue'} variant="light">
            <Text size="sm">
              {pendingUsesFirstMile
                ? 'Received first-mile truck and driver details are pulled from the first-mile record. GRN uses booking cargo, quantity and weight.'
                : 'Register the customer or third-party truck and driver before export receiving and GRN.'}
            </Text>
          </Alert>
          <Table.ScrollContainer minWidth={900}>
            <Table withTableBorder highlightOnHover verticalSpacing="xs">
              <Table.Thead>
                <Table.Tr>
                  <Table.Th>Booking</Table.Th>
                  <Table.Th>Customer</Table.Th>
                  <Table.Th>TIN / Phone</Table.Th>
                  <Table.Th>Container / Cargo</Table.Th>
                  <Table.Th>Qty / Package</Table.Th>
                  <Table.Th>Weight</Table.Th>
                  <Table.Th>Received at</Table.Th>
                </Table.Tr>
              </Table.Thead>
              <Table.Tbody>
                {pendingReceiveRows.map((booking) => (
                  <Table.Tr key={booking.id}>
                    <Table.Td>
                      <Text size="sm" fw={600}>{booking.reference}</Text>
                      <Text size="xs" c="dimmed">{booking.id.slice(0, 8)}...</Text>
                    </Table.Td>
                    <Table.Td>{booking.customer ?? '-'}</Table.Td>
                    <Table.Td>
                      <Stack gap={0}>
                        <Text size="xs">{booking.customerTin ?? '-'}</Text>
                        <Text size="xs" c="dimmed">{booking.customerPhone ?? '-'}</Text>
                      </Stack>
                    </Table.Td>
                    <Table.Td>
                      <Stack gap={0}>
                        <Text size="xs">{booking.containerNumber ?? booking.cargoDescription ?? booking.cargo ?? '-'}</Text>
                        <Text size="xs" c="dimmed">{booking.freightType ?? '-'}</Text>
                      </Stack>
                    </Table.Td>
                    <Table.Td>
                      {[
                        booking.containerQuantity != null ? `${booking.containerQuantity} unit(s)` : null,
                        booking.containerPackagingType,
                      ].filter(Boolean).join(' / ') || '-'}
                    </Table.Td>
                    <Table.Td>{formatNumber(Number(booking.weight))}</Table.Td>
                    <Table.Td>{formatDate(receivedAt)}</Table.Td>
                  </Table.Tr>
                ))}
              </Table.Tbody>
            </Table>
          </Table.ScrollContainer>
          <TruckEntranceFields
            value={truckForm}
            onChange={setTruckForm}
            lockedFields={lockedTruckFields}
            packagingFreightType={packagingFreightType}
            allowTruckWeighing={!pendingUsesFirstMile}
          />
          <Group justify="flex-end">
            <Button variant="default" onClick={() => setTruckOpen(false)} disabled={bulkReceive.isPending}>
              Cancel
            </Button>
            <Button leftSection={<Truck size={16} />} loading={bulkReceive.isPending} onClick={receive}>
              Register Arrival & Generate GRN
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Stack>
  );
}

/** Export received items awaiting inspection before loading. */
function ExportReceivedTab({ enabled, onChanged }: { enabled: boolean; onChanged?: () => void }) {
  const { toast } = useToast();
  const { data: rows = [], isLoading } = useQuery(
    api.warehouses.receivedExport.queryOptions({ enabled }),
  );
  const inspectMutation = useMutation(
    api.warehouses.bulkMarkInspected.mutationOptions(),
  );
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [confirmAction, setConfirmAction] = useState<ConfirmAction | null>(null);
  const [expandedRow, setExpandedRow] = useState<string | null>(null);
  const [inspectId, setInspectId] = useState<string | null>(null);

  const pendingRows = rows.filter((r) => r.inspectionStatus !== 'PASSED');
  const allSelected = pendingRows.length > 0 && selected.size === pendingRows.length;
  const someSelected = selected.size > 0 && !allSelected;
  const toggleAll = () =>
    setSelected(allSelected ? new Set() : new Set(pendingRows.map((r) => r.id)));
  const toggleOne = (id: string) =>
    setSelected((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });

  const markInspected = async () => {
    if (selected.size === 0) {
      toast({ variant: 'destructive', title: 'Select at least one item' });
      return;
    }
    try {
      const r = await inspectMutation.mutateAsync({ inventoryIds: [...selected] });
      toast({
        title: `${r.inspectedCount} marked inspected`,
        description: skippedSummary(r.skippedCount, r.results),
      });
      setSelected(new Set());
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Mark inspected failed', description: extractErrorMessage(error) });
    }
  };

  return (
    <Stack gap="sm" mt="sm">
      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          Selected: <b>{selected.size}</b> / {pendingRows.length} received
        </Text>
        <Button
          size="compact-sm"
          color="indigo"
          leftSection={<ClipboardCheck size={14} />}
          disabled={selected.size === 0}
          loading={inspectMutation.isPending}
          onClick={() =>
            setConfirmAction({
              title: 'Mark inspected',
              message: `Mark ${selected.size} selected item(s) as inspection PASSED?`,
              confirmLabel: `Mark ${selected.size} inspected`,
              run: markInspected,
            })
          }
        >
          Mark Selected as Inspected
        </Button>
      </Group>

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : rows.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No received export items awaiting inspection.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1350}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                <Table.Th w={34} />
                <Table.Th w={40}>
                  <Checkbox
                    aria-label="Select all"
                    checked={allSelected}
                    indeterminate={someSelected}
                    onChange={toggleAll}
                  />
                </Table.Th>
                <Table.Th>Booking Ref</Table.Th>
                <Table.Th>GRN</Table.Th>
                <Table.Th>Customer Name</Table.Th>
                <Table.Th>Container / Cargo Items</Table.Th>
                <Table.Th>Cargo Type</Table.Th>
                <Table.Th>Weight</Table.Th>
                <Table.Th>Route</Table.Th>
                <Table.Th>Inspection</Table.Th>
                <Table.Th>Status</Table.Th>
                <Table.Th ta="right">Actions</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {rows.map((r: ReadyToLoadRow) => {
                const selectable = r.inspectionStatus !== 'PASSED';
                return (
                  <Fragment key={r.id}>
                  <Table.Tr>
                    <Table.Td>
                      <ActionIcon
                        variant="subtle"
                        color="gray"
                        aria-label="Show containers"
                        onClick={() => setExpandedRow(expandedRow === r.id ? null : r.id)}
                      >
                        {expandedRow === r.id ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                      </ActionIcon>
                    </Table.Td>
                    <Table.Td>
                      <Checkbox
                        aria-label={`Select ${r.bookingReference ?? r.id}`}
                        checked={selected.has(r.id)}
                        disabled={!selectable}
                        onChange={() => toggleOne(r.id)}
                      />
                    </Table.Td>
                    <Table.Td>
                      <Text size="sm" fw={600}>{r.bookingReference ?? '—'}</Text>
                    </Table.Td>
                    <Table.Td>
                      <GrnDocumentButton inventoryId={r.id} grnNumber={r.grnNumber} />
                    </Table.Td>
                    <Table.Td>{r.customerName ?? '—'}</Table.Td>
                    <Table.Td>{r.containerNumber ?? '—'}</Table.Td>
                    <Table.Td>{r.cargoType ?? '—'}</Table.Td>
                    <Table.Td>{formatNumber(Number(r.weight))}</Table.Td>
                    <Table.Td>
                      {r.origin || r.destination ? `${r.origin ?? '?'} → ${r.destination ?? '?'}` : '—'}
                    </Table.Td>
                    <Table.Td>
                      <Badge color={r.inspectionStatus === 'PASSED' ? 'green' : 'orange'} variant="light" size="sm">
                        {r.inspectionStatus ?? 'PENDING'}
                      </Badge>
                    </Table.Td>
                    <Table.Td>
                      <InventoryStatusBadge status={r.status as InventoryStatus} />
                    </Table.Td>
                    <Table.Td ta="right">
                      <Button size="compact-xs" variant="light" color="orange" onClick={() => setInspectId(r.id)}>
                        Inspect / Report
                      </Button>
                    </Table.Td>
                  </Table.Tr>
                  {expandedRow === r.id && (
                    <BookingItemsExpansion
                      bookingId={r.bookingId}
                      colSpan={18}
                      bulkFallback={r.cargoType ? `Bulk cargo — ${r.cargoType}, ${formatNumber(Number(r.weight))} t` : undefined}
                    />
                  )}
                  </Fragment>
                );
              })}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}

      <InspectionReportModal
        inventoryId={inspectId}
        opened={Boolean(inspectId)}
        onClose={() => setInspectId(null)}
      />
      <ConfirmActionModal action={confirmAction} onClose={() => setConfirmAction(null)} />
    </Stack>
  );
}

/** Export items that passed inspection and are queued to be loaded onto a train. */
function ReadyToLoadTab({ enabled, onChanged }: { enabled: boolean; onChanged?: () => void }) {
  const { toast } = useToast();
  const { data: rows = [], isLoading } = useQuery(
    api.warehouses.readyToLoadExport.queryOptions({ enabled }),
  );
  const qc = useQueryClient();
  const [trainPickerOpen, setTrainPickerOpen] = useState(false);
  const [expandedRow, setExpandedRow] = useState<string | null>(null);
  const [targetScheduleId, setTargetScheduleId] = useState<string | null>(null);
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const allSelected = rows.length > 0 && selected.size === rows.length;
  const someSelected = selected.size > 0 && !allSelected;
  const toggleAll = () => setSelected(allSelected ? new Set() : new Set(rows.map((r) => r.id)));
  const toggleOne = (id: string) =>
    setSelected((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });

  // Loading is always onto a SPECIFIC pre-dispatch train. No train -> no auto-load.
  const { data: trains = [], isLoading: trainsLoading } = useQuery({
    queryKey: ['warehouse-inventory', 'loadable-trains'],
    queryFn: () => warehouseService.getLoadableTrains(),
    enabled: enabled && trainPickerOpen,
  });
  const loadOntoTrain = useMutation({
    mutationFn: async ({ scheduleId, onlyIds }: { scheduleId: string; onlyIds: string[] }) => {
      const items = await warehouseService.getTrainLoadableItems(scheduleId);
      let loadableIds = items.filter((i) => i.loadable).map((i) => i.id);
      // When rows are checked, load only those; otherwise load every loadable item.
      if (onlyIds.length) {
        const picked = new Set(onlyIds);
        loadableIds = loadableIds.filter((id) => picked.has(id));
      }
      if (!loadableIds.length) {
        throw new Error(
          onlyIds.length
            ? 'None of the selected items have an allocated wagon on this train'
            : 'No ready items with an allocated wagon on this train',
        );
      }
      return warehouseService.loadItemsOntoTrain(scheduleId, loadableIds);
    },
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
      void qc.invalidateQueries({ queryKey: ['warehouse-loadings'] });
    },
  });


  const confirmLoad = async () => {
    if (!targetScheduleId) {
      toast({ variant: 'destructive', title: 'Select a train to load onto' });
      return;
    }
    try {
      const r = await loadOntoTrain.mutateAsync({
        scheduleId: targetScheduleId,
        onlyIds: [...selected],
      });
      const train = trains.find((t) => t.scheduleId === targetScheduleId);
      toast({
        title: `${r.loadedCount} item(s) loaded onto train ${train?.trainNumber ?? ''}`.trim(),
        description: r.skippedCount
          ? `${r.skippedCount} skipped — ${r.results.find((x) => x.reason)?.reason ?? 'see results'}`
          : undefined,
      });
      setTrainPickerOpen(false);
      setTargetScheduleId(null);
      setSelected(new Set());
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Load failed', description: extractErrorMessage(error) });
    }
  };

  return (
    <Stack gap="sm" mt="sm">
      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          {selected.size > 0 ? (
            <><b>{selected.size}</b> of {rows.length} selected</>
          ) : (
            <><b>{rows.length}</b> item{rows.length !== 1 ? 's' : ''} ready to load</>
          )}
        </Text>
        <Button
          size="compact-sm"
          variant="filled"
          color="teal"
          leftSection={<Truck size={14} />}
          disabled={rows.length === 0}
          onClick={() => setTrainPickerOpen(true)}
        >
          {selected.size > 0 ? `Load Selected (${selected.size})` : 'Auto Load Ready Items'}
        </Button>
      </Group>

      <Modal
        opened={trainPickerOpen}
        onClose={() => setTrainPickerOpen(false)}
        title="Load ready items onto a train"
        centered
        size="lg"
      >
        <Stack gap="md">
          {trainsLoading ? (
            <Group justify="center" py="md"><Loader size="sm" /></Group>
          ) : trains.length === 0 ? (
            <Alert color="yellow" variant="light" icon={<Info size={16} />}>
              No train available. Auto-loading needs a scheduled (not yet dispatched) train with
              these bookings assigned — schedule the train and allocate wagons first.
            </Alert>
          ) : (
            <Select
              label="Available trains"
              placeholder="Select the train to load onto"
              data={trains.map((t) => ({
                value: t.scheduleId,
                label: `${t.trainNumber ?? t.scheduleId.slice(0, 8)} · ${t.origin ?? '?'} → ${t.destination ?? '?'} · dep ${t.departureTime ? formatDate(t.departureTime) : '—'} · ${t.readyCount} ready`,
              }))}
              value={targetScheduleId}
              onChange={setTargetScheduleId}
              searchable
            />
          )}
          <Group justify="flex-end">
            <Button variant="default" onClick={() => setTrainPickerOpen(false)} disabled={loadOntoTrain.isPending}>
              Cancel
            </Button>
            <Button
              color="teal"
              leftSection={<Truck size={14} />}
              loading={loadOntoTrain.isPending}
              disabled={!targetScheduleId}
              onClick={confirmLoad}
            >
              Load onto this train
            </Button>
          </Group>
        </Stack>
      </Modal>

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : rows.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No EXPORT items with inspection PASSED waiting to be loaded.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1200}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                <Table.Th w={40}>
                  <Checkbox
                    aria-label="Select all"
                    checked={allSelected}
                    indeterminate={someSelected}
                    onChange={toggleAll}
                  />
                </Table.Th>
                <Table.Th w={34} />
                <Table.Th>Booking Ref</Table.Th>
                <Table.Th>GRN</Table.Th>
                <Table.Th>Customer Name</Table.Th>
                <Table.Th>Container #</Table.Th>
                <Table.Th>Cargo Type</Table.Th>
                <Table.Th>Weight</Table.Th>
                <Table.Th>Route</Table.Th>
                <Table.Th>Inspection</Table.Th>
                <Table.Th>Status</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {rows.map((r: ReadyToLoadRow) => (
                <Fragment key={r.id}>
                <Table.Tr>
                  <Table.Td>
                    <Checkbox
                      aria-label={`Select ${r.bookingReference ?? r.id}`}
                      checked={selected.has(r.id)}
                      onChange={() => toggleOne(r.id)}
                    />
                  </Table.Td>
                  <Table.Td>
                    <ActionIcon
                      variant="subtle"
                      color="gray"
                      aria-label="Show containers"
                      onClick={() => setExpandedRow(expandedRow === r.id ? null : r.id)}
                    >
                      {expandedRow === r.id ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                    </ActionIcon>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" fw={600}>{r.bookingReference ?? '—'}</Text>
                  </Table.Td>
                  <Table.Td>
                    <GrnDocumentButton inventoryId={r.id} grnNumber={r.grnNumber} />
                  </Table.Td>
                  <Table.Td>{r.customerName ?? '—'}</Table.Td>
                  <Table.Td>{r.containerNumber ?? '—'}</Table.Td>
                  <Table.Td>{r.cargoType ?? '—'}</Table.Td>
                  <Table.Td>{formatNumber(Number(r.weight))}</Table.Td>
                  <Table.Td>
                    {r.origin || r.destination ? `${r.origin ?? '?'} → ${r.destination ?? '?'}` : '—'}
                  </Table.Td>
                  <Table.Td>
                    <Badge color="green" variant="light" size="sm">
                      {r.inspectionStatus ?? '—'}
                    </Badge>
                  </Table.Td>
                  <Table.Td>
                    <InventoryStatusBadge status={r.status as InventoryStatus} />
                  </Table.Td>
                </Table.Tr>
                {expandedRow === r.id && (
                  <BookingItemsExpansion
                    bookingId={r.bookingId}
                    colSpan={11}
                    bulkFallback={r.cargoType ? `Bulk cargo — ${r.cargoType}, ${formatNumber(Number(r.weight))} t` : undefined}
                  />
                )}
              </Fragment>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </Stack>
  );
}

/**
 * Export items that are LOADED onto a wagon. Serves both the "Loaded" tab (read-only)
 * and the "Dispatch Queue" tab (dispatchable=true → selection + Dispatch actions).
 */
function LoadedExportTab({
  enabled,
  dispatchable,
  onChanged,
}: {
  enabled: boolean;
  dispatchable: boolean;
  onChanged?: () => void;
}) {
  const { toast } = useToast();
  const { data: rows = [], isLoading } = useQuery(
    api.warehouses.loadedExport.queryOptions({ enabled }),
  );
  const [confirmAction, setConfirmAction] = useState<ConfirmAction | null>(null);
  const [expandedRow, setExpandedRow] = useState<string | null>(null);
  const bulkDispatch = useMutation(
    api.warehouses.bulkDispatchExport.mutationOptions(),
  );
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const allSelected = rows.length > 0 && selected.size === rows.length;
  const someSelected = selected.size > 0 && !allSelected;
  const toggleAll = () => setSelected(allSelected ? new Set() : new Set(rows.map((r) => r.id)));
  const toggleOne = (id: string) =>
    setSelected((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });

  const dispatch = async (inventoryIds: string[]) => {
    if (inventoryIds.length === 0) {
      toast({ variant: 'destructive', title: 'Select at least one item' });
      return;
    }
    try {
      const r = await bulkDispatch.mutateAsync(inventoryIds);
      toast({
        title: `${r.dispatchedCount} dispatched`,
        description: skippedSummary(r.skippedCount, r.results),
      });
      setSelected(new Set());
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Dispatch failed', description: extractErrorMessage(error) });
    }
  };

  return (
    <Stack gap="sm" mt="sm">
      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          {dispatchable ? (
            <>
              Selected: <b>{selected.size}</b> / {rows.length} loaded
            </>
          ) : (
            <>
              <b>{rows.length}</b> item{rows.length !== 1 ? 's' : ''} loaded
            </>
          )}
        </Text>
        {dispatchable && (
          <Group gap="xs">
            <Button
              size="compact-sm"
              variant="default"
              disabled={rows.length === 0}
              loading={bulkDispatch.isPending}
              onClick={() =>
                setConfirmAction({
                  title: 'Dispatch all',
                  message: `Dispatch all ${rows.length} loaded item(s)? They leave warehouse inventory for the train.`,
                  confirmLabel: `Dispatch ${rows.length}`,
                  run: () => dispatch(rows.map((r) => r.id)),
                })
              }
            >
              Dispatch All
            </Button>
            <Button
              size="compact-sm"
              color="green"
              leftSection={<Truck size={14} />}
              disabled={selected.size === 0}
              loading={bulkDispatch.isPending}
              onClick={() =>
                setConfirmAction({
                  title: 'Dispatch selected',
                  message: `Dispatch ${selected.size} selected item(s)? They leave warehouse inventory for the train.`,
                  confirmLabel: `Dispatch ${selected.size}`,
                  run: () => dispatch([...selected]),
                })
              }
            >
              Dispatch Selected
            </Button>
          </Group>
        )}
      </Group>

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : rows.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No LOADED export items {dispatchable ? 'waiting to dispatch' : 'yet'}.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1200}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                {dispatchable && (
                  <Table.Th w={40}>
                    <Checkbox
                      aria-label="Select all"
                      checked={allSelected}
                      indeterminate={someSelected}
                      onChange={toggleAll}
                    />
                  </Table.Th>
                )}
                <Table.Th w={34} />
                <Table.Th>Booking Ref</Table.Th>
                <Table.Th>GRN</Table.Th>
                <Table.Th>Customer Name</Table.Th>
                <Table.Th>Container #</Table.Th>
                <Table.Th>Cargo Type</Table.Th>
                <Table.Th>Weight</Table.Th>
                <Table.Th>Route</Table.Th>
                <Table.Th>Status</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {rows.map((r: ReadyToLoadRow) => (
                <Fragment key={r.id}>
                <Table.Tr>
                  {dispatchable && (
                    <Table.Td>
                      <Checkbox
                        aria-label={`Select ${r.bookingReference ?? r.id}`}
                        checked={selected.has(r.id)}
                        onChange={() => toggleOne(r.id)}
                      />
                    </Table.Td>
                  )}
                  <Table.Td>
                    <ActionIcon
                      variant="subtle"
                      color="gray"
                      aria-label="Show containers"
                      onClick={() => setExpandedRow(expandedRow === r.id ? null : r.id)}
                    >
                      {expandedRow === r.id ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                    </ActionIcon>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" fw={600}>{r.bookingReference ?? '—'}</Text>
                  </Table.Td>
                  <Table.Td>
                    <GrnDocumentButton inventoryId={r.id} grnNumber={r.grnNumber} />
                  </Table.Td>
                  <Table.Td>{r.customerName ?? '—'}</Table.Td>
                  <Table.Td>{r.containerNumber ?? '—'}</Table.Td>
                  <Table.Td>{r.cargoType ?? '—'}</Table.Td>
                  <Table.Td>{formatNumber(Number(r.weight))}</Table.Td>
                  <Table.Td>
                    {r.origin || r.destination ? `${r.origin ?? '?'} → ${r.destination ?? '?'}` : '—'}
                  </Table.Td>
                  <Table.Td>
                    <InventoryStatusBadge status={r.status as InventoryStatus} />
                  </Table.Td>
                </Table.Tr>
                {expandedRow === r.id && (
                  <BookingItemsExpansion
                    bookingId={r.bookingId}
                    colSpan={11}
                    bulkFallback={r.cargoType ? `Bulk cargo — ${r.cargoType}, ${formatNumber(Number(r.weight))} t` : undefined}
                  />
                )}
                </Fragment>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
      <ConfirmActionModal action={confirmAction} onClose={() => setConfirmAction(null)} />
    </Stack>
  );
}

const importLocationTypesForFreight = (freightType: string | null | undefined) => {
  const normalized = (freightType ?? '').toUpperCase();
  if (normalized === 'CONTAINER') {
    return { yardTypes: ['CONTAINER_YARD', 'GENERAL_CARGO_YARD'], zoneTypes: ['CONTAINER_ZONE', 'GENERAL_CARGO_ZONE'] };
  }
  return { yardTypes: ['BULK_YARD', 'GENERAL_CARGO_YARD'], zoneTypes: ['BULK_ZONE', 'GENERAL_CARGO_ZONE'] };
};

const isImportContainerFreight = (freightType: string | null | undefined) =>
  (freightType ?? '').toUpperCase() === 'CONTAINER';

/**
 * Yard/zone types valid for the freight being received — used to filter the receive
 * location pickers so the yard list matches the cargo. Container freight → container
 * yards only; bulk / break-bulk → bulk, general-cargo, hazardous, or cold-storage.
 * Union across the given freight types; empty input → no restriction (show all).
 */
const yardZoneTypesForFreights = (freightTypes: Array<string | null | undefined>) => {
  const yardTypes = new Set<string>();
  const zoneTypes = new Set<string>();
  for (const freightType of freightTypes) {
    const normalized = (freightType ?? '').toUpperCase();
    if (!normalized) continue;
    if (normalized === 'CONTAINER') {
      yardTypes.add('CONTAINER_YARD');
      zoneTypes.add('CONTAINER_ZONE');
    } else {
      ['BULK_YARD', 'GENERAL_CARGO_YARD', 'HAZARDOUS_YARD', 'COLD_STORAGE_YARD'].forEach((t) => yardTypes.add(t));
      ['BULK_ZONE', 'GENERAL_CARGO_ZONE', 'HAZARDOUS_ZONE', 'COLD_STORAGE_ZONE'].forEach((t) => zoneTypes.add(t));
    }
  }
  return { yardTypes: [...yardTypes], zoneTypes: [...zoneTypes] };
};

const isImportUnloadPending = (item: ImportTrainItem) =>
  !item.currentStatus || item.currentStatus === 'RECEIVED';

/** Assigned bookings/items for an arrived import train with per-booking unload locations. */
function ImportTrainDetailTable({
  train,
  warehouses,
  yards,
  zones,
  assignments,
  onAssignmentChange,
  onReadyChange,
}: {
  train: ImportTrain;
  warehouses: Warehouse[];
  yards: WarehouseYard[];
  zones: WarehouseZone[];
  assignments: Record<string, ImportUnloadAssignmentDraft>;
  onAssignmentChange: (bookingId: string, draft: ImportUnloadAssignmentDraft) => void;
  onReadyChange: (ready: boolean) => void;
}) {
  const { data: items = [], isLoading } = useQuery(
    api.warehouses.importTrainItems.queryOptions({
      input: { scheduleId: train.scheduleId },
      enabled: Boolean(train.scheduleId),
    }),
  );
  const warehouseOptions = useMemo(
    () => warehouses.map((warehouse) => ({ value: warehouse.id, label: `${warehouse.name} (${warehouse.code})` })),
    [warehouses],
  );

  useEffect(() => {
    const pending = items.filter(isImportUnloadPending);
    onReadyChange(
      pending.length > 0 &&
        pending.every((item) => {
          const draft = assignments[item.bookingId];
          return Boolean(draft?.warehouseId && draft.yardId && draft.zoneId);
        }),
    );
  }, [assignments, items]);

  if (isLoading) {
    return (
      <Group justify="center" py="md">
        <Loader size="sm" />
      </Group>
    );
  }
  if (items.length === 0) {
    return (
      <Text c="dimmed" ta="center" py="md" size="sm">
        No assigned bookings on this train.
      </Text>
    );
  }

  return (
    <Table withTableBorder verticalSpacing="xs" fz="xs">
      <Table.Thead>
        <Table.Tr>
          <Table.Th>Wagon</Table.Th>
          <Table.Th>Booking Ref</Table.Th>
          <Table.Th>Customer Name</Table.Th>
          <Table.Th>Container #</Table.Th>
          <Table.Th>Cargo Type</Table.Th>
          <Table.Th>Weight</Table.Th>
          <Table.Th>Arrival</Table.Th>
          <Table.Th>Warehouse</Table.Th>
          <Table.Th>Yard</Table.Th>
          <Table.Th>Zone</Table.Th>
          <Table.Th>Inspection</Table.Th>
          <Table.Th>Current Status</Table.Th>
          <Table.Th>Last Mile</Table.Th>
          <Table.Th>Pickup Option</Table.Th>
        </Table.Tr>
      </Table.Thead>
      <Table.Tbody>
        {items.map((it: ImportTrainItem) => {
          const draft = assignments[it.bookingId] ?? {};
          const { yardTypes, zoneTypes } = importLocationTypesForFreight(it.freightType);
          const yardOptions = yards
            .filter((yard) => yard.warehouseId === draft.warehouseId && yardTypes.includes(yard.type))
            .map((yard) => ({ value: yard.id, label: `${yard.name} (${yard.code})` }));
          const zoneOptions = zones
            .filter((zone) => zone.yardId === draft.yardId && zoneTypes.includes(zone.type))
            .map((zone) => ({ value: zone.id, label: `${zone.name} (${zone.code})` }));
          const pending = isImportUnloadPending(it);

          return (
          <Table.Tr key={`${it.bookingId}-${it.sequenceNo ?? 'wagon'}`}>
            <Table.Td>
              <Text size="xs" fw={600}>
                {it.sequenceNo ? `#${it.sequenceNo}` : '-'} {it.wagonNumber ?? ''}
              </Text>
            </Table.Td>
            <Table.Td>
              <Text size="xs" fw={600}>{it.bookingReference ?? '—'}</Text>
            </Table.Td>
            <Table.Td>{it.customerName ?? '—'}</Table.Td>
            <Table.Td>{it.containerNumber ?? '—'}</Table.Td>
            <Table.Td>{it.cargoType ?? '—'}</Table.Td>
            <Table.Td>{formatNumber(Number(it.weight))}</Table.Td>
            <Table.Td>{formatDate(it.arrivalTime)}</Table.Td>
            <Table.Td>
              <Select
                placeholder="Warehouse"
                data={warehouseOptions}
                value={draft.warehouseId ?? null}
                onChange={(value) => onAssignmentChange(it.bookingId, { warehouseId: value ?? undefined })}
                searchable
                disabled={!pending}
                w={210}
              />
            </Table.Td>
            <Table.Td>
              <Select
                placeholder={isImportContainerFreight(it.freightType) ? 'Container yard' : 'Bulk yard'}
                data={yardOptions}
                value={draft.yardId ?? null}
                onChange={(value) =>
                  onAssignmentChange(it.bookingId, { ...draft, yardId: value ?? undefined, zoneId: undefined })
                }
                searchable
                disabled={!pending || !draft.warehouseId}
                w={190}
              />
            </Table.Td>
            <Table.Td>
              <Select
                placeholder={isImportContainerFreight(it.freightType) ? 'Container zone' : 'Bulk zone'}
                data={zoneOptions}
                value={draft.zoneId ?? null}
                onChange={(value) => onAssignmentChange(it.bookingId, { ...draft, zoneId: value ?? undefined })}
                searchable
                disabled={!pending || !draft.yardId}
                w={190}
              />
            </Table.Td>
            <Table.Td>
              <Badge size="xs" variant="light" color={it.inspectionStatus === 'PASSED' ? 'green' : 'gray'}>
                {it.inspectionStatus ?? 'Not inspected'}
              </Badge>
            </Table.Td>
            <Table.Td>
              <Badge size="xs" variant="light" color="gray">{it.currentStatus ?? '—'}</Badge>
            </Table.Td>
            <Table.Td>
              <Badge size="xs" variant="light" color={it.lastMileRequested ? 'blue' : 'gray'}>
                {it.lastMileRequested ? 'Yes' : 'No'}
              </Badge>
            </Table.Td>
            <Table.Td>{it.pickupOption}</Table.Td>
          </Table.Tr>
          );
        })}
      </Table.Tbody>
    </Table>
  );
}

/** Import Arrive Queue: arrived IMPORT trains, with Open (detail) + Auto Unload per train. */
const getPendingUnloadBookings = (train: ImportTrain) =>
  train.pendingUnloadBookings ?? train.totalBookings;

const isFullyUnloaded = (train: ImportTrain) =>
  Boolean(train.fullyUnloaded) || (train.totalBookings > 0 && getPendingUnloadBookings(train) === 0);

function ImportArriveQueueTab({
  enabled,
  onChanged,
}: {
  enabled: boolean;
  onChanged?: () => void;
}) {
  const { toast } = useToast();
  const { data: trains = [], isLoading } = useQuery(
    api.warehouses.importArriveQueue.queryOptions({ enabled }),
  );
  const { data: warehouses = [], isLoading: warehousesLoading } = useQuery(
    api.warehouses.list.queryOptions({ input: { filter: { status: 'ACTIVE' } }, enabled }),
  );
  const { data: yards = [] } = useAllWarehouseYards();
  const { data: zones = [] } = useAllWarehouseZones();
  const autoUnloadMutation = useMutation(
    api.warehouses.autoUnloadArrivedBookings.mutationOptions(),
  );
  const [openId, setOpenId] = useState<string | null>(null);
  const [confirmAction, setConfirmAction] = useState<ConfirmAction | null>(null);
  const [busyId, setBusyId] = useState<string | null>(null);
  const [assignmentsBySchedule, setAssignmentsBySchedule] = useState<
    Record<string, Record<string, ImportUnloadAssignmentDraft>>
  >({});
  const [readyBySchedule, setReadyBySchedule] = useState<Record<string, boolean>>({});

  const autoUnload = async (train: ImportTrain) => {
    const assignments = Object.entries(assignmentsBySchedule[train.scheduleId] ?? {})
      .filter((entry): entry is [string, Required<ImportUnloadAssignmentDraft>] =>
        Boolean(entry[1].warehouseId && entry[1].yardId && entry[1].zoneId),
      )
      .map(([bookingId, draft]) => ({
        bookingId,
        warehouseId: draft.warehouseId,
        yardId: draft.yardId,
        zoneId: draft.zoneId,
      }));

    if (!readyBySchedule[train.scheduleId] || assignments.length === 0) {
      toast({
        variant: 'destructive',
        title: 'Assign locations',
        description: 'Select warehouse, yard and zone for each pending booking before unloading.',
      });
      return;
    }

    if (isFullyUnloaded(train)) {
      toast({
        title: 'Already unloaded',
        description: `${train.trainNumber ?? 'This train'} has no remaining bookings to auto unload.`,
      });
      return;
    }

    setBusyId(train.scheduleId);
    try {
      const r = await autoUnloadMutation.mutateAsync({ scheduleId: train.scheduleId, assignments });
      const alreadyUnloaded = r.unloadedCount === 0 && r.skippedCount > 0 && r.failedCount === 0;
      const firstReason = r.results.find((item) => item.reason)?.reason;
      const extra = [
        skippedSummary(r.skippedCount, r.results) ?? '',
        r.failedCount ? `${r.failedCount} failed` : '',
      ]
        .filter(Boolean)
        .join(', ');
      toast({
        title: alreadyUnloaded ? 'Already unloaded' : `${r.unloadedCount} unloaded`,
        description: alreadyUnloaded ? firstReason ?? 'This train is already in warehouse inventory.' : extra || undefined,
      });
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Auto unload failed', description: extractErrorMessage(error) });
    } finally {
      setBusyId(null);
    }
  };

  return (
    <Stack gap="sm" mt="sm">
      <Text size="sm" c="dimmed">
        <b>{trains.length}</b> arrived import train{trains.length !== 1 ? 's' : ''}
      </Text>

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : trains.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No arrived import trains. Trains appear here once their schedule status is ARRIVED.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1500}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Schedule ID</Table.Th>
                <Table.Th>Train #</Table.Th>
                <Table.Th>Route</Table.Th>
                <Table.Th>Origin</Table.Th>
                <Table.Th>Destination</Table.Th>
                <Table.Th>Arrival Time</Table.Th>
                <Table.Th ta="center">Bookings</Table.Th>
                <Table.Th ta="center">Containers</Table.Th>
                <Table.Th ta="center">Cargoes</Table.Th>
                <Table.Th>Status</Table.Th>
                <Table.Th ta="right">Actions</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {trains.map((t: ImportTrain) => {
                const isOpen = openId === t.scheduleId;
                const fullyUnloaded = isFullyUnloaded(t);
                const unloadedBookings = t.unloadedBookings ?? t.totalBookings - getPendingUnloadBookings(t);
                return (
                  <Fragment key={t.scheduleId}>
                    <Table.Tr>
                      <Table.Td>
                        <Text size="xs" c="dimmed">{t.scheduleId.slice(0, 8)}…</Text>
                      </Table.Td>
                      <Table.Td>
                        <Text size="sm" fw={600}>{t.trainNumber ?? '—'}</Text>
                      </Table.Td>
                      <Table.Td>{t.route ?? '—'}</Table.Td>
                      <Table.Td>{t.origin ?? '—'}</Table.Td>
                      <Table.Td>{t.destination ?? '—'}</Table.Td>
                      <Table.Td>{formatDate(t.arrivalTime)}</Table.Td>
                      <Table.Td ta="center">{t.totalBookings}</Table.Td>
                      <Table.Td ta="center">{t.totalContainers}</Table.Td>
                      <Table.Td ta="center">{t.totalCargoes}</Table.Td>
                      <Table.Td>
                        <Stack gap={2}>
                          <Badge color="indigo" variant="light" size="sm">
                            {t.status}
                          </Badge>
                          <Text size="xs" c="dimmed">
                            {Math.max(unloadedBookings, 0)}/{t.totalBookings} unloaded
                          </Text>
                        </Stack>
                      </Table.Td>
                      <Table.Td ta="right">
                        <Group gap="xs" justify="flex-end" wrap="nowrap">
                          <Button
                            size="compact-xs"
                            variant="light"
                            leftSection={isOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                            onClick={() => setOpenId(isOpen ? null : t.scheduleId)}
                          >
                            Open
                          </Button>
                          <Button
                            size="compact-xs"
                            color={fullyUnloaded ? 'gray' : 'indigo'}
                            leftSection={<Truck size={14} />}
                            loading={busyId === t.scheduleId}
                            disabled={fullyUnloaded || t.totalBookings === 0 || !readyBySchedule[t.scheduleId] || warehousesLoading}
                            onClick={() =>
                              setConfirmAction({
                                title: 'Auto unload train',
                                message: `Unload all arrived bookings from train ${t.trainNumber ?? t.scheduleId.slice(0, 8)} into their assigned warehouse locations?`,
                                confirmLabel: 'Unload train',
                                run: () => autoUnload(t),
                              })
                            }
                          >
                            {fullyUnloaded ? 'Already Unloaded' : 'Auto Unload Arrived Bookings'}
                          </Button>
                        </Group>
                      </Table.Td>
                    </Table.Tr>
                    {isOpen && (
                      <Table.Tr>
                        <Table.Td colSpan={11} bg="var(--mantine-color-gray-0)">
                          <ImportTrainDetailTable
                            train={t}
                            warehouses={warehouses}
                            yards={yards}
                            zones={zones}
                            assignments={assignmentsBySchedule[t.scheduleId] ?? {}}
                            onAssignmentChange={(bookingId, draft) =>
                              setAssignmentsBySchedule((current) => ({
                                ...current,
                                [t.scheduleId]: {
                                  ...(current[t.scheduleId] ?? {}),
                                  [bookingId]: draft.warehouseId ? draft : {},
                                },
                              }))
                            }
                            onReadyChange={(ready) =>
                              setReadyBySchedule((current) => ({ ...current, [t.scheduleId]: ready }))
                            }
                          />
                        </Table.Td>
                      </Table.Tr>
                    )}
                  </Fragment>
                );
              })}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
      <ConfirmActionModal action={confirmAction} onClose={() => setConfirmAction(null)} />
    </Stack>
  );
}

/**
 * Import Unloaded Queue (Batch 9): all unloaded import items with the destination-inspection columns.
 * Multi-select + Mark Selected as Inspected (import passed → READY_FOR_PICKUP), and the per-item
 * Inspect / Report action stays for damage / images / weight-loss detail.
 */
function ImportUnloadedQueueTab({ enabled }: { enabled: boolean }) {
  const { toast } = useToast();
  const qc = useQueryClient();
  const { data: rows = [], isLoading } = useQuery(
    api.warehouses.importUnloadedQueue.queryOptions({ enabled }),
  );
  const inspectMutation = useMutation(
    api.warehouses.bulkMarkInspected.mutationOptions(),
  );
  const readyMutation = useMutation(api.warehouses.markReadyForPickup.mutationOptions());
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [confirmAction, setConfirmAction] = useState<ConfirmAction | null>(null);
  const [expandedRow, setExpandedRow] = useState<string | null>(null);
  const [inspectId, setInspectId] = useState<string | null>(null);
  const [busyId, setBusyId] = useState<string | null>(null);
  const [viewItem, setViewItem] = useState<WarehouseInventoryItem | null>(null);
  const [historyItem, setHistoryItem] = useState<WarehouseInventoryItem | null>(null);
  const [feeItem, setFeeItem] = useState<WarehouseInventoryItem | null>(null);
  const [releaseItem, setReleaseItem] = useState<WarehouseInventoryItem | null>(null);
  const [deliverItem, setDeliverItem] = useState<WarehouseInventoryItem | null>(null);
  const [containerItemsItem, setContainerItemsItem] = useState<WarehouseInventoryItem | null>(null);
  const [storeItem, setStoreItem] = useState<WarehouseInventoryItem | null>(null);
  const [moveItem, setMoveItem] = useState<WarehouseInventoryItem | null>(null);

  const allSelected = rows.length > 0 && selected.size === rows.length;
  const someSelected = selected.size > 0 && !allSelected;
  const selectAll = () => setSelected(new Set(rows.map((r) => r.id)));
  const unselectAll = () => setSelected(new Set());
  const toggleOne = (id: string) =>
    setSelected((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });

  const markInspected = async () => {
    if (selected.size === 0) {
      toast({ variant: 'destructive', title: 'Select at least one item' });
      return;
    }
    try {
      const r = await inspectMutation.mutateAsync({ inventoryIds: [...selected] });
      toast({
        title: `${r.inspectedCount} marked inspected`,
        description: skippedSummary(r.skippedCount, r.results),
      });
      setSelected(new Set());
      void qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
    } catch (error) {
      toast({ variant: 'destructive', title: 'Mark inspected failed', description: extractErrorMessage(error) });
    }
  };

  const toInventoryItem = (row: ImportUnloadedItem): WarehouseInventoryItem =>
    ({
      id: row.id,
      bookingId: row.bookingId,
      quantity: 1,
      weight: Number(row.weight) || 0,
      grnNumber: row.grnNumber,
      status: row.currentStatus,
      arrivedAt: row.arrivalTime,
      unloadedAt: row.arrivalTime,
      inspectionStatus: row.inspectionStatus,
      releaseDate: row.releaseDate,
      releaseOrderReference: row.releaseOrderReference,
      handoverDocumentReference: row.handoverDocumentReference,
      handoverDocumentDate: row.handoverDocumentDate,
      deliveredAt: row.deliveredAt,
      // Carries the saved [Exit Inspection] block so Truck Leaving opens with the
      // arrival details (plate, driver, tare, gate-in) read-only instead of blank.
      notes: row.notes,
      booking: row.bookingId
        ? {
            id: row.bookingId,
            reference: row.bookingReference ?? row.bookingId,
            tradeDirection: 'IMPORT',
            lastMileDeliveryAddress: row.lastMileRequested ? row.pickupOption : null,
            customerTruckPlateNumber: row.customerTruckPlateNumber,
            customerTruckDriverName: row.customerTruckDriverName,
            customerTruckType: row.customerTruckType,
            customerTruckContainerNumber: row.customerTruckContainerNumber,
            customerTruckAssignedAt: row.customerTruckAssignedAt,
          }
        : null,
    }) as unknown as WarehouseInventoryItem;

  const runRowAction = async (row: ImportUnloadedItem, label: string, fn: () => Promise<unknown>) => {
    setBusyId(row.id);
    try {
      await fn();
      toast({ title: label });
      void qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
    } catch (error) {
      toast({ variant: 'destructive', title: 'Action failed', description: extractErrorMessage(error) });
    } finally {
      setBusyId(null);
    }
  };

  const openHandoverDocument = async (row: ImportUnloadedItem) => {
    setBusyId(row.id);
    const pdfWindow = window.open('', '_blank');
    try {
      const response = await warehouseService.downloadHandoverDocument(row.id);
      openPdfBlob(response.data, `handover-${row.bookingReference ?? row.id}.pdf`, pdfWindow);
      void qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
    } catch (error) {
      pdfWindow?.close();
      toast({ variant: 'destructive', title: 'Handover document failed', description: await extractDownloadErrorMessage(error) });
    } finally {
      setBusyId(null);
    }
  };

  const openReleaseDocument = async (row: ImportUnloadedItem) => {
    setBusyId(row.id);
    const pdfWindow = window.open('', '_blank');
    try {
      const response = await warehouseService.downloadReleaseDocument(row.id);
      openPdfBlob(response.data, `release-${row.bookingReference ?? row.id}.pdf`, pdfWindow);
    } catch (error) {
      pdfWindow?.close();
      toast({ variant: 'destructive', title: 'Exit paper failed', description: await extractDownloadErrorMessage(error) });
    } finally {
      setBusyId(null);
    }
  };

  return (
    <Stack gap="sm" mt="sm">
      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          Selected: <b>{selected.size}</b> / {rows.length} unloaded
        </Text>
        <Group gap="xs">
          <Button size="compact-sm" variant="default" disabled={rows.length === 0} onClick={selectAll}>
            Select All
          </Button>
          <Button size="compact-sm" variant="default" disabled={selected.size === 0} onClick={unselectAll}>
            Unselect All
          </Button>
          <Button
            size="compact-sm"
            color="indigo"
            leftSection={<ClipboardCheck size={14} />}
            disabled={selected.size === 0}
            loading={inspectMutation.isPending}
            onClick={() =>
              setConfirmAction({
                title: 'Mark inspected',
                message: `Mark ${selected.size} selected item(s) as inspection PASSED? Passed import items become ready for pickup.`,
                confirmLabel: `Mark ${selected.size} inspected`,
                run: markInspected,
              })
            }
          >
            Mark Selected as Inspected
          </Button>
        </Group>
      </Group>

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : rows.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No unloaded import items. Items appear here after Auto Unload on an arrived train.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1650}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                <Table.Th w={34} />
                <Table.Th w={40}>
                  <Checkbox
                    aria-label="Select all"
                    checked={allSelected}
                    indeterminate={someSelected}
                    onChange={() => (allSelected ? unselectAll() : selectAll())}
                  />
                </Table.Th>
                <Table.Th>Booking Ref</Table.Th>
                <Table.Th>GRN</Table.Th>
                <Table.Th>Customer Name</Table.Th>
                <Table.Th>Arrival Time</Table.Th>
                <Table.Th>Container #</Table.Th>
                <Table.Th>Cargo Type</Table.Th>
                <Table.Th>Weight</Table.Th>
                <Table.Th>Train Schedule</Table.Th>
                <Table.Th>Inspection</Table.Th>
                <Table.Th>Pickup Option</Table.Th>
                <Table.Th>Last Mile</Table.Th>
                <Table.Th>Current Status</Table.Th>
                <Table.Th ta="right">Actions</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {rows.map((r: ImportUnloadedItem) => (
                <Fragment key={r.id}>
                <Table.Tr>
                  <Table.Td>
                    <ActionIcon
                      variant="subtle"
                      color="gray"
                      aria-label="Show containers"
                      onClick={() => setExpandedRow(expandedRow === r.id ? null : r.id)}
                    >
                      {expandedRow === r.id ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                    </ActionIcon>
                  </Table.Td>
                  <Table.Td>
                    <Checkbox
                      aria-label={`Select ${r.bookingReference ?? r.id}`}
                      checked={selected.has(r.id)}
                      onChange={() => toggleOne(r.id)}
                    />
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" fw={600}>{r.bookingReference ?? '—'}</Text>
                  </Table.Td>
                  <Table.Td>
                    <GrnDocumentButton inventoryId={r.id} grnNumber={r.grnNumber} />
                  </Table.Td>
                  <Table.Td>{r.customerName ?? '—'}</Table.Td>
                  <Table.Td>{formatDate(r.arrivalTime)}</Table.Td>
                  <Table.Td>{r.containerNumber ?? '—'}</Table.Td>
                  <Table.Td>{r.cargoType ?? '—'}</Table.Td>
                  <Table.Td>{formatNumber(Number(r.weight))}</Table.Td>
                  <Table.Td>{r.trainSchedule ?? '—'}</Table.Td>
                  <Table.Td>
                    <Badge color={r.inspectionStatus === 'PASSED' ? 'green' : 'gray'} variant="light" size="sm">
                      {r.inspectionStatus ?? 'Not inspected'}
                    </Badge>
                  </Table.Td>
                  <Table.Td>{r.pickupOption}</Table.Td>
                  <Table.Td>
                    <Badge color={r.lastMileRequested ? 'blue' : 'gray'} variant="light" size="sm">
                      {r.lastMileRequested ? 'Yes' : 'No'}
                    </Badge>
                  </Table.Td>
                  <Table.Td>
                    <InventoryStatusBadge status={r.currentStatus as InventoryStatus} />
                  </Table.Td>
                  <Table.Td ta="right">
                    <Group gap="xs" justify="flex-end" wrap="nowrap">
                      <Tooltip label="View details" withArrow>
                        <ActionIcon variant="subtle" color="gray" onClick={() => setContainerItemsItem(toInventoryItem(r))}>
                          <Eye size={16} />
                        </ActionIcon>
                      </Tooltip>
                      {/* Primary stage action stays visible; the rest live under the kebab. */}
                      {/* Stays visible after the first exit — multi-truck bookings
                          weigh each truck in and out until all have left. */}
                      {r.currentStatus === 'READY_FOR_PICKUP' && r.hasAssignedTruck && (
                        <Button
                          size="compact-xs"
                          variant="light"
                          color="yellow"
                          leftSection={<Truck size={14} />}
                          onClick={() => setReleaseItem(toInventoryItem(r))}
                        >
                          {r.releaseOrderReference ? 'Truck Arrival / Leaving' : 'Truck Arrival'}
                        </Button>
                      )}
                      {r.currentStatus === 'READY_FOR_PICKUP' && r.releaseDate && (
                        <Button
                          size="compact-xs"
                          variant="light"
                          color="orange"
                          leftSection={<FileText size={14} />}
                          loading={busyId === r.id}
                          onClick={() => openReleaseDocument(r)}
                        >
                          Exit Paper
                        </Button>
                      )}
                      <Menu shadow="md" width={240} position="bottom-end" withinPortal>
                        <Menu.Target>
                          <ActionIcon variant="subtle" color="gray" aria-label="More actions" loading={busyId === r.id}>
                            <MoreHorizontal size={16} />
                          </ActionIcon>
                        </Menu.Target>
                        <Menu.Dropdown>
                          {r.currentStatus === 'UNLOADED' && (
                            <Menu.Item leftSection={<MapPin size={14} />} onClick={() => setStoreItem(toInventoryItem(r))}>
                              Store…
                            </Menu.Item>
                          )}
                          {r.currentStatus !== 'UNLOADED' && (
                            <Menu.Item leftSection={<ArrowRightLeft size={14} />} onClick={() => setMoveItem(toInventoryItem(r))}>
                              Move…
                            </Menu.Item>
                          )}
                          {['UNLOADED', 'STORED'].includes(r.currentStatus) && r.inspectionStatus === 'PASSED' && (
                            <Menu.Item onClick={() => runRowAction(r, 'Ready for pickup', () => readyMutation.mutateAsync(r.id))}>
                              Ready for pickup
                            </Menu.Item>
                          )}
                          {r.currentStatus === 'READY_FOR_PICKUP' && (
                            <Menu.Item
                              leftSection={<Truck size={14} />}
                              disabled={!r.hasAssignedTruck}
                              onClick={() => setReleaseItem(toInventoryItem(r))}
                            >
                              {r.hasAssignedTruck
                                ? r.releaseOrderReference
                                  ? 'Truck arrival / leaving'
                                  : 'Truck arrival'
                                : 'Truck arrival — assign a truck first'}
                            </Menu.Item>
                          )}
                          {r.currentStatus === 'READY_FOR_PICKUP' && r.releaseDate && (
                            <Menu.Item leftSection={<FileText size={14} />} onClick={() => openReleaseDocument(r)}>
                              Exit paper
                            </Menu.Item>
                          )}
                          {r.currentStatus === 'READY_FOR_PICKUP' && r.releaseDate && (
                            <Menu.Item onClick={() => setDeliverItem(toInventoryItem(r))}>Deliver</Menu.Item>
                          )}
                          {r.inspectionStatus === 'PASSED' && (
                            <Menu.Item leftSection={<FileText size={14} />} onClick={() => openHandoverDocument(r)}>
                              {r.handoverDocumentReference ? 'View handover' : 'Handover'}
                            </Menu.Item>
                          )}
                          <Menu.Item onClick={() => setInspectId(r.id)}>Inspect / report</Menu.Item>
                          {/* Double handling is decided once the goods are off
                              the wagon (every row here is unloaded) — Yes is
                              what makes the fee rule bill this booking. */}
                          <Menu.Divider />
                          <Menu.Label>
                            Double handling —{' '}
                            {r.doubleHandling == null ? 'not set' : r.doubleHandling ? 'Yes' : 'No'}
                          </Menu.Label>
                          <Menu.Item
                            leftSection={
                              r.doubleHandling === true ? <Check size={14} /> : <Layers size={14} />
                            }
                            disabled={!r.bookingId || r.doubleHandling === true}
                            onClick={() =>
                              runRowAction(r, 'Double handling: Yes — fee rule applies', () =>
                                warehouseService.setDoubleHandling(r.bookingId as string, true),
                              )
                            }
                          >
                            Yes — apply fee
                          </Menu.Item>
                          <Menu.Item
                            leftSection={
                              r.doubleHandling === false ? <Check size={14} /> : <Layers size={14} />
                            }
                            disabled={!r.bookingId || r.doubleHandling === false}
                            onClick={() =>
                              runRowAction(r, 'Double handling: No', () =>
                                warehouseService.setDoubleHandling(r.bookingId as string, false),
                              )
                            }
                          >
                            No
                          </Menu.Item>
                          <Menu.Divider />
                          <Menu.Item leftSection={<PackageCheck size={14} />} onClick={() => setFeeItem(toInventoryItem(r))}>
                            Storage / fee preview
                          </Menu.Item>
                          <Menu.Item leftSection={<History size={14} />} onClick={() => setHistoryItem(toInventoryItem(r))}>
                            History
                          </Menu.Item>
                        </Menu.Dropdown>
                      </Menu>
                    </Group>
                  </Table.Td>
                </Table.Tr>
                {expandedRow === r.id && (
                  <BookingItemsExpansion
                    bookingId={r.bookingId}
                    colSpan={16}
                    bulkFallback={r.cargoType ? `Bulk cargo — ${r.cargoType}, ${formatNumber(Number(r.weight))} t` : undefined}
                  />
                )}
                </Fragment>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}

      <InspectionReportModal
        opened={Boolean(inspectId)}
        onClose={() => setInspectId(null)}
        inventoryId={inspectId}
      />
      <InventoryDetailModal opened={Boolean(viewItem)} onClose={() => setViewItem(null)} item={viewItem} />
      <InventoryHistoryModal opened={Boolean(historyItem)} onClose={() => setHistoryItem(null)} item={historyItem} />
      <FeePreviewModal
        opened={Boolean(feeItem)}
        onClose={() => setFeeItem(null)}
        inventoryId={feeItem?.id ?? null}
      />
      <ReleaseOrderModal opened={Boolean(releaseItem)} onClose={() => setReleaseItem(null)} item={releaseItem} />
      <StoreInventoryModal opened={Boolean(storeItem)} onClose={() => setStoreItem(null)} item={storeItem} />
      <MoveInventoryModal opened={Boolean(moveItem)} onClose={() => setMoveItem(null)} item={moveItem} />
      <DeliverInventoryModal opened={Boolean(deliverItem)} onClose={() => setDeliverItem(null)} item={deliverItem} />
      <ContainerItemsModal
        opened={Boolean(containerItemsItem)}
        onClose={() => setContainerItemsItem(null)}
        bookingId={containerItemsItem?.booking?.id ?? null}
        bookingReference={containerItemsItem?.booking?.reference ?? null}
      />
      <ConfirmActionModal action={confirmAction} onClose={() => setConfirmAction(null)} />
    </Stack>
  );
}

/**
 * Import Dispatch Queue (Batch 10): inspected import items that are PICKUP_READY (READY_FOR_PICKUP),
 * awaiting Customer Pickup (release → deliver), Store, or Dispatch. Reuses InventoryWorkbench so all
 * existing actions + modals stay intact; Last Mile shows only when the booking requested door delivery.
 * Nothing is stored automatically — Store is an explicit operator action.
 */
function ImportDispatchQueueTab({ enabled }: { enabled: boolean }) {
  const { toast } = useToast();
  const { data: items = [], isLoading } = useQuery(
    api.warehouses.listInventory.queryOptions({
      input: { filter: enabled ? { status: 'READY_FOR_PICKUP' } : undefined },
    }),
  );

  return (
    <Stack gap="sm" mt="sm">
      <Text size="sm" c="dimmed">
        <b>{items.length}</b> pickup-ready item{items.length !== 1 ? 's' : ''}
      </Text>
      <InventoryWorkbench
        items={items}
        isLoading={isLoading}
        onLastMile={(it) =>
          toast({
            title: 'Last mile delivery',
            description: `Door delivery for ${it.booking?.reference ?? it.id} — handled in the next batch.`,
          })
        }
      />
    </Stack>
  );
}

type WarehouseFlowDirection = 'IMPORT' | 'EXPORT' | 'BOTH';
type ImportWarehouseTab = 'arrive-queue' | 'unloaded-queue' | 'dispatch-queue' | 'locate-booking';
type ExportWarehouseTab = 'receive-queue' | 'received' | 'ready-to-load' | 'loaded' | 'dispatch-queue' | 'locate-booking';

interface WarehouseQueueTab<TValue extends string> {
  value: TValue;
  label: string;
  icon: React.ReactNode;
  count?: number;
}

interface WarehouseFlowWorkbenchProps {
  direction?: WarehouseFlowDirection;
  enabled?: boolean;
  onChanged?: () => void;
  focusedBookingId?: string;
  focusedBookingLabel?: string;
}

function WarehouseQueueTabs<TValue extends string>({
  value,
  onChange,
  tabs,
}: {
  value: TValue;
  onChange: (value: TValue) => void;
  tabs: WarehouseQueueTab<TValue>[];
}) {
  return (
    <Tabs
      value={value}
      onChange={(next) => onChange((next as TValue) ?? value)}
      variant="pills"
      color="edr-green"
      keepMounted={false}
      classNames={{ list: 'ov-tablist', tab: 'ov-tab' }}
    >
      <ScrollArea type="auto" scrollbarSize={6} offsetScrollbars="x">
        <Tabs.List style={{ flexWrap: 'nowrap', width: 'max-content' }}>
          {tabs.map((tab) => {
            const active = value === tab.value;
            return (
              <Tabs.Tab
                key={tab.value}
                value={tab.value}
                leftSection={tab.icon}
                rightSection={
                  tab.count !== undefined ? (
                    <Badge
                      size="sm"
                      radius="sm"
                      variant={active ? 'white' : 'light'}
                      color={active ? 'edr-green' : 'gray'}
                      styles={
                        active
                          ? { root: { background: 'rgba(255,255,255,0.9)', color: '#15805f' } }
                          : undefined
                      }
                    >
                      {tab.count}
                    </Badge>
                  ) : undefined
                }
              >
                {tab.label}
              </Tabs.Tab>
            );
          })}
        </Tabs.List>
      </ScrollArea>
    </Tabs>
  );
}

function LocateBookingTab({ enabled }: { enabled: boolean }) {
  const [draft, setDraft] = useState<InventoryInquiryFilter>({});
  const [applied, setApplied] = useState<InventoryInquiryFilter>({});
  const [viewResult, setViewResult] = useState<InventoryInquiryResult | null>(null);
  const hasSearch = Boolean(
    applied.bookingReference ||
      applied.containerNumber ||
      applied.goodsName ||
      applied.cargoType ||
      applied.status,
  );
  const { data: results = [], isFetching } = useInventoryInquiry(applied, enabled && hasSearch);

  const normalizeDraft = (): InventoryInquiryFilter => ({
    bookingReference: draft.bookingReference?.trim() || undefined,
    containerNumber: draft.containerNumber?.trim() || undefined,
    goodsName: draft.goodsName?.trim() || undefined,
    cargoType: draft.cargoType?.trim() || undefined,
    status: draft.status,
  });

  const runSearch = () => setApplied(normalizeDraft());
  const reset = () => {
    setDraft({});
    setApplied({});
  };

  return (
    <Stack gap="md" mt="sm">
      <Group gap="sm" wrap="wrap">
        <TextInput
          label="Booking reference"
          placeholder="e.g. BK-2026-000051"
          value={draft.bookingReference ?? ''}
          onChange={(e) => setDraft((filter) => ({ ...filter, bookingReference: e.currentTarget.value || undefined }))}
          onKeyDown={(e) => {
            if (e.key === 'Enter') runSearch();
          }}
          w={230}
        />
        <TextInput
          label="Container number"
          placeholder="e.g. MSKU1234567"
          value={draft.containerNumber ?? ''}
          onChange={(e) => setDraft((filter) => ({ ...filter, containerNumber: e.currentTarget.value || undefined }))}
          onKeyDown={(e) => {
            if (e.key === 'Enter') runSearch();
          }}
          w={220}
        />
        <TextInput
          label="Goods / cargo"
          placeholder="Coffee, steel, etc."
          value={draft.goodsName ?? draft.cargoType ?? ''}
          onChange={(e) => {
            const value = e.currentTarget.value || undefined;
            setDraft((filter) => ({ ...filter, goodsName: value, cargoType: value }));
          }}
          onKeyDown={(e) => {
            if (e.key === 'Enter') runSearch();
          }}
          w={200}
        />
        <Select
          label="Status"
          placeholder="Any"
          clearable
          data={inventoryStatusOptions}
          value={draft.status ?? null}
          onChange={(value) => setDraft((filter) => ({ ...filter, status: value as InventoryInquiryFilter['status'] }))}
          w={190}
        />
      </Group>
      <Group gap="xs">
        <Button leftSection={<Search size={16} />} onClick={runSearch}>
          Locate Booking
        </Button>
        <Button variant="default" onClick={reset}>
          Reset
        </Button>
      </Group>

      {isFetching ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : !hasSearch ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          Search by booking reference, container number, cargo or status to locate inventory.
        </Text>
      ) : results.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No inventory found for the current filters.
        </Text>
      ) : (
        <WarehouseInquiryTable results={results} onView={setViewResult} />
      )}

      <InventoryInquiryDetailModal
        opened={Boolean(viewResult)}
        onClose={() => setViewResult(null)}
        result={viewResult}
      />
    </Stack>
  );
}

function ImportWarehouseTabs({ enabled, onChanged }: { enabled: boolean; onChanged?: () => void }) {
  const [activeTab, setActiveTab] = useState<ImportWarehouseTab>('arrive-queue');
  const { data: arriveRows = [] } = useQuery(api.warehouses.importArriveQueue.queryOptions({ enabled }));
  const { data: unloadedRows = [] } = useQuery(api.warehouses.importUnloadedQueue.queryOptions({ enabled }));
  const { data: dispatchRows = [] } = useQuery(api.warehouses.importPickupReadyQueue.queryOptions({ enabled }));
  const tabs: WarehouseQueueTab<ImportWarehouseTab>[] = [
    {
      value: 'arrive-queue',
      label: 'Arrival Queue',
      icon: <PackageOpen size={17} strokeWidth={1.85} />,
      count: arriveRows.length,
    },
    {
      value: 'unloaded-queue',
      label: 'Unloaded Queue',
      icon: <ClipboardCheck size={17} strokeWidth={1.85} />,
      count: unloadedRows.length,
    },
    {
      value: 'dispatch-queue',
      label: 'Dispatch Queue',
      icon: <Send size={17} strokeWidth={1.85} />,
      count: dispatchRows.length,
    },
    {
      value: 'locate-booking',
      label: 'Locate Booking',
      icon: <Search size={17} strokeWidth={1.85} />,
    },
  ];

  return (
    <Stack gap="md">
      <WarehouseQueueTabs value={activeTab} onChange={setActiveTab} tabs={tabs} />

      {activeTab === 'arrive-queue' && (
        <ImportArriveQueueTab enabled={enabled} onChanged={onChanged} />
      )}
      {activeTab === 'unloaded-queue' && (
        <ImportUnloadedQueueTab enabled={enabled} />
      )}
      {activeTab === 'dispatch-queue' && (
        <ImportDispatchQueueTab enabled={enabled} />
      )}
      {activeTab === 'locate-booking' && (
        <LocateBookingTab enabled={enabled} />
      )}
    </Stack>
  );
}

function ExportWarehouseTabs({
  enabled,
  location,
  onChanged,
  focusedBookingId,
  focusedBookingLabel,
}: {
  enabled: boolean;
  location: Location;
  onChanged?: () => void;
  focusedBookingId?: string;
  focusedBookingLabel?: string;
}) {
  const [activeTab, setActiveTab] = useState<ExportWarehouseTab>('receive-queue');
  const { data: eligibleRows = [] } = useQuery(
    api.warehouses.eligibleBookings.queryOptions({
      input: { direction: 'EXPORT' },
      enabled,
    }),
  );
  const { data: receivedRows = [] } = useQuery(api.warehouses.receivedExport.queryOptions({ enabled }));
  const { data: readyRows = [] } = useQuery(api.warehouses.readyToLoadExport.queryOptions({ enabled }));
  const { data: loadedRows = [] } = useQuery(api.warehouses.loadedExport.queryOptions({ enabled }));
  const exportEligibleCount = useMemo(
    () => eligibleRows.filter((row) => row.direction === 'EXPORT').length,
    [eligibleRows],
  );
  const tabs: WarehouseQueueTab<ExportWarehouseTab>[] = [
    {
      value: 'receive-queue',
      label: 'Receive to Warehouse',
      icon: <Truck size={17} strokeWidth={1.85} />,
      count: exportEligibleCount,
    },
    {
      value: 'received',
      label: 'Received',
      icon: <ClipboardCheck size={17} strokeWidth={1.85} />,
      count: receivedRows.length,
    },
    {
      value: 'ready-to-load',
      label: 'Ready To Load',
      icon: <Train size={17} strokeWidth={1.85} />,
      count: readyRows.length,
    },
    {
      value: 'loaded',
      label: 'Loaded',
      icon: <PackageCheck size={17} strokeWidth={1.85} />,
      count: loadedRows.length,
    },
    {
      value: 'dispatch-queue',
      label: 'Dispatch Queue',
      icon: <Send size={17} strokeWidth={1.85} />,
      count: loadedRows.length,
    },
    {
      value: 'locate-booking',
      label: 'Locate Booking',
      icon: <Search size={17} strokeWidth={1.85} />,
    },
  ];

  return (
    <Stack gap="md">
      <WarehouseQueueTabs value={activeTab} onChange={setActiveTab} tabs={tabs} />

      {activeTab === 'receive-queue' && (
        <EligibleTab
          direction="EXPORT"
          location={location}
          enabled={enabled}
          onChanged={onChanged}
          focusedBookingId={focusedBookingId}
          focusedBookingLabel={focusedBookingLabel}
        />
      )}
      {activeTab === 'received' && (
        <ExportReceivedTab enabled={enabled} onChanged={onChanged} />
      )}
      {activeTab === 'ready-to-load' && (
        <ReadyToLoadTab enabled={enabled} onChanged={onChanged} />
      )}
      {activeTab === 'loaded' && (
        <LoadedExportTab enabled={enabled} dispatchable={false} onChanged={onChanged} />
      )}
      {activeTab === 'dispatch-queue' && (
        <LoadedExportTab enabled={enabled} dispatchable onChanged={onChanged} />
      )}
      {activeTab === 'locate-booking' && (
        <LocateBookingTab enabled={enabled} />
      )}
    </Stack>
  );
}

export function WarehouseFlowWorkbench({
  direction = 'BOTH',
  enabled = true,
  onChanged,
  focusedBookingId,
  focusedBookingLabel,
}: WarehouseFlowWorkbenchProps) {
  const [location, setLocation] = useState<Location>({ warehouseId: '', yardId: '', zoneId: '' });
  const [tab, setTab] = useState<Exclude<WarehouseFlowDirection, 'BOTH'>>(
    direction === 'EXPORT' ? 'EXPORT' : 'IMPORT',
  );
  const activeDirection = direction === 'BOTH' ? tab : direction;

  // Match the yard/zone list to the freight being received (container → container
  // yards, etc). Same query key as the export tab, so React Query dedupes it.
  const { data: eligibleForLocation = [] } = useQuery(
    api.warehouses.eligibleBookings.queryOptions({
      input: { direction: activeDirection },
      enabled: enabled && activeDirection === 'EXPORT',
    }),
  );
  const { yardTypes: allowedYardTypes, zoneTypes: allowedZoneTypes } = useMemo(
    () =>
      yardZoneTypesForFreights(
        eligibleForLocation
          .filter((r) => r.direction === activeDirection)
          .map((r) => r.freightType),
      ),
    [eligibleForLocation, activeDirection],
  );

  useEffect(() => {
    if (enabled) setLocation({ warehouseId: '', yardId: '', zoneId: '' });
  }, [enabled, direction]);

  return (
    <Stack gap="md">
      {activeDirection === 'EXPORT' && (
        <LocationSelects
          value={location}
          onChange={setLocation}
          allowedYardTypes={allowedYardTypes}
          allowedZoneTypes={allowedZoneTypes}
        />
      )}

      {direction === 'BOTH' ? (
        <Tabs value={tab} onChange={(v) => setTab((v as 'IMPORT' | 'EXPORT') ?? 'IMPORT')}>
          <Tabs.List>
            <Tabs.Tab value="IMPORT" leftSection={<PackageSearch size={16} />}>
              Import
            </Tabs.Tab>
            <Tabs.Tab value="EXPORT" leftSection={<Truck size={16} />}>
              Export
            </Tabs.Tab>
          </Tabs.List>

          <Tabs.Panel value="IMPORT">
            <ImportWarehouseTabs enabled={enabled} onChanged={onChanged} />
          </Tabs.Panel>
          <Tabs.Panel value="EXPORT">
            <ExportWarehouseTabs
              enabled={enabled}
              location={location}
              onChanged={onChanged}
              focusedBookingId={focusedBookingId}
              focusedBookingLabel={focusedBookingLabel}
            />
          </Tabs.Panel>
        </Tabs>
      ) : activeDirection === 'IMPORT' ? (
        <ImportWarehouseTabs enabled={enabled} onChanged={onChanged} />
      ) : (
        <ExportWarehouseTabs
          enabled={enabled}
          location={location}
          onChanged={onChanged}
          focusedBookingId={focusedBookingId}
          focusedBookingLabel={focusedBookingLabel}
        />
      )}
    </Stack>
  );
}

/** New bulk Receive: Import / Export tabs with eligible PAID bookings. */
function BulkReceiveModal({ opened, onClose, onReceived, bookingId, bookingLabel, direction = 'BOTH' }: ReceiveInventoryModalProps) {
  return (
    <Modal opened={opened} onClose={onClose} title="Receive at warehouse" centered size="80rem">
      <Stack gap="md">
        <WarehouseFlowWorkbench
          enabled={opened}
          direction={direction}
          onChanged={onReceived}
          focusedBookingId={bookingId}
          focusedBookingLabel={bookingLabel}
        />

        <Group justify="flex-end" mt="sm">
          <Button variant="default" onClick={onClose}>
            Close
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

interface SingleFormState {
  warehouseId: string;
  yardId: string;
  zoneId: string;
  quantity: number | '';
  weight: number | '';
  volume: number | '';
  notes: string;
}

/** Legacy single-booking receive — used when a specific bookingId is supplied. */
function SingleBookingReceiveModal({
  opened,
  onClose,
  bookingId,
  bookingLabel,
  onReceived,
}: ReceiveInventoryModalProps) {
  const { toast } = useToast();
  const receiveMutation = useMutation(
    api.warehouses.receiveInventory.mutationOptions(),
  );
  const [selectedBooking, setSelectedBooking] = useState(bookingId ?? '');
  const [form, setForm] = useState<SingleFormState>({
    warehouseId: '',
    yardId: '',
    zoneId: '',
    quantity: '',
    weight: '',
    volume: '',
    notes: '',
  });
  const [truckForm, setTruckForm] = useState<TruckEntranceFormState>(emptyTruckEntrance());

  useEffect(() => {
    if (opened) {
      setSelectedBooking(bookingId ?? '');
      setForm({ warehouseId: '', yardId: '', zoneId: '', quantity: '', weight: '', volume: '', notes: '' });
      setTruckForm(emptyTruckEntrance());
    }
  }, [opened, bookingId]);

  const location: Location = { warehouseId: form.warehouseId, yardId: form.yardId, zoneId: form.zoneId };

  const handleSubmit = async () => {
    if (!selectedBooking.trim()) {
      toast({ variant: 'destructive', title: 'Booking is required' });
      return;
    }
    if (!form.warehouseId || !form.yardId || !form.zoneId) {
      toast({ variant: 'destructive', title: 'Select warehouse, yard and zone' });
      return;
    }
    if (!truckForm.truckPlateNumber.trim() || !truckForm.driverName.trim() || !truckForm.driverPhone.trim() || truckForm.entranceTareWeightKg === '') {
      toast({ variant: 'destructive', title: 'Truck, driver and entrance tare weight are required' });
      return;
    }
    const payload: ReceiveInventoryPayload = {
      bookingId: selectedBooking.trim(),
      warehouseId: form.warehouseId,
      yardId: form.yardId,
      zoneId: form.zoneId,
      quantity: 0,
      weight: 0,
      volume: form.volume === '' ? undefined : Number(form.volume),
      notes: form.notes.trim() || undefined,
      truckEntrance: toTruckEntrancePayload(truckForm),
    };
    try {
      await receiveMutation.mutateAsync(payload);
      toast({ title: 'Inventory received' });
      onReceived?.();
      onClose();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Receive failed', description: extractErrorMessage(error) });
    }
  };

  return (
    <Modal opened={opened} onClose={onClose} title="Receive at warehouse" centered size="lg">
      <Stack gap="md">
        {bookingId ? (
          <TextInput label="Booking" value={bookingLabel ?? bookingId} readOnly />
        ) : (
          <BookingSelect label="Booking" value={selectedBooking} onChange={setSelectedBooking} />
        )}

        <LocationSelects value={location} onChange={(next) => setForm((f) => ({ ...f, ...next }))} />

        <Alert icon={<Info size={16} />} color="blue" variant="light">
          <Text size="sm">
            Customer, TIN, phone, quantity and weight are pulled from the selected booking when the GRN is generated.
          </Text>
        </Alert>

        <Group grow>
          <NumberInput
            label="Volume (m³)"
            placeholder="Optional"
            min={0}
            value={form.volume}
            onChange={(value) => setForm((f) => ({ ...f, volume: value === '' ? '' : Number(value) }))}
          />
        </Group>

        <TruckEntranceFields value={truckForm} onChange={setTruckForm} />

        <Textarea
          label="Notes"
          placeholder="Optional notes"
          autosize
          minRows={2}
          value={form.notes}
          onChange={(e) => {
            const v = e.currentTarget.value;
            setForm((f) => ({ ...f, notes: v }));
          }}
        />

        <Group justify="flex-end" mt="sm">
          <Button variant="default" onClick={onClose} disabled={receiveMutation.isPending}>
            Cancel
          </Button>
          <Button onClick={handleSubmit} loading={receiveMutation.isPending}>
            Receive inventory and generate GRN
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

export function ReceiveInventoryModal(props: ReceiveInventoryModalProps) {
  // Locked to a booking → legacy single receive; otherwise the Import/Export bulk flow.
  return props.bookingId && props.mode !== 'bulk' ? <SingleBookingReceiveModal {...props} /> : <BulkReceiveModal {...props} />;
}
