import { Fragment, useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Badge,
  Button,
  Checkbox,
  Group,
  Loader,
  Modal,
  NumberInput,
  Select,
  Stack,
  Table,
  Tabs,
  Text,
  Textarea,
  TextInput,
} from '@mantine/core';
import { ChevronDown, ChevronRight, ClipboardCheck, Info, PackageSearch, Train, Truck } from 'lucide-react';

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

import { api } from '@/services/api';
import { useToast } from '@/hooks/use-toast';
import type {
  ImportTrain,
  ImportTrainItem,
  ImportUnloadedItem,
  ReadyToLoadRow,
  ReceiveInventoryPayload,
} from '@/types/warehouse';
import { BookingSelect } from './BookingSelect';
import { InspectionReportModal } from './InspectionReportModal';
import { InventoryWorkbench } from './InventoryWorkbench';
import { extractErrorMessage, formatDate, formatNumber } from './options';

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

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

/** Cascading Warehouse → Yard → Zone selectors (ACTIVE only). */
function LocationSelects({
  value,
  onChange,
}: {
  value: Location;
  onChange: (next: Location) => void;
}) {
  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')
        .map((y) => ({ value: y.id, label: `${y.name} (${y.code})` })),
    [yardsQuery.data],
  );
  const zoneOptions = useMemo(
    () =>
      (zonesQuery.data ?? [])
        .filter((z) => z.status === 'ACTIVE')
        .map((z) => ({ value: z.id, label: `${z.name} (${z.code})` })),
    [zonesQuery.data],
  );

  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,
}: {
  direction: 'IMPORT' | 'EXPORT';
  location: Location;
  enabled: boolean;
  onChanged?: () => void;
}) {
  const { toast } = useToast();
  const { data: allRows = [], isLoading } = useQuery(
    api.warehouses.eligibleBookings.queryOptions({ enabled }),
  );
  const rows = useMemo(() => allRows.filter((r) => r.direction === direction), [allRows, direction]);
  const bulkReceive = useMutation(api.warehouses.bulkReceive.mutationOptions());
  const loadPassed = useMutation(api.warehouses.loadPassedExport.mutationOptions());
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const locationReady = Boolean(location.warehouseId && location.yardId && location.zoneId);
  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 receive = async (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;
    }
    try {
      const r = await bulkReceive.mutateAsync({ direction, ...location, bookingIds });
      toast({
        title: `${r.receivedCount} received at ${direction === 'EXPORT' ? 'facility' : 'warehouse'}`,
        description: r.skippedCount ? `${r.skippedCount} skipped` : undefined,
      });
      setSelected(new Set());
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Receive failed', description: extractErrorMessage(error) });
    }
  };

  const loadPassedExport = async () => {
    try {
      const r = await loadPassed.mutateAsync(undefined);
      toast({
        title: `${r.loadedCount} loaded`,
        description: r.skippedCount ? `${r.skippedCount} skipped — inspection not passed` : undefined,
      });
      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: <b>{selected.size}</b> / {rows.length} eligible
        </Text>
        <Group gap="xs">
          {direction === 'EXPORT' && (
            <Button
              size="compact-sm"
              variant="light"
              color="teal"
              leftSection={<Truck size={14} />}
              loading={loadPassed.isPending}
              onClick={loadPassedExport}
            >
              Load Passed Export Items
            </Button>
          )}
          <Button
            size="compact-sm"
            variant="default"
            disabled={!locationReady || rows.length === 0}
            loading={bulkReceive.isPending}
            onClick={() => receive(rows.map((r) => r.id))}
          >
            Receive All Eligible
          </Button>
          <Button
            size="compact-sm"
            disabled={!locationReady || selected.size === 0}
            loading={bulkReceive.isPending}
            onClick={() => receive([...selected])}
          >
            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>
      ) : rows.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No eligible PAID {direction.toLowerCase()} bookings to receive.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1700}>
          <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>Booking ID</Table.Th>
                <Table.Th>Customer ID</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 #</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>
                <Table.Th ta="right">Actions</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {rows.map((r) => (
                <Table.Tr key={r.id}>
                  <Table.Td>
                    <Checkbox
                      aria-label={`Select ${r.reference}`}
                      checked={selected.has(r.id)}
                      onChange={() => toggleOne(r.id)}
                    />
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" fw={600}>
                      {r.reference}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="xs" c="dimmed">{r.id.slice(0, 8)}…</Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="xs" c="dimmed">{r.customerId ? `${r.customerId.slice(0, 8)}…` : '—'}</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>—</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>
                  <Table.Td ta="right">
                    <Button
                      size="compact-xs"
                      variant="light"
                      disabled={!locationReady}
                      loading={bulkReceive.isPending}
                      onClick={() => receive([r.id])}
                    >
                      Receive
                    </Button>
                  </Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </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 loadPassed = useMutation(api.warehouses.loadPassedExport.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 autoLoad = async () => {
    try {
      const r = await loadPassed.mutateAsync(undefined);
      toast({
        title: `${r.loadedCount} items loaded`,
        description: r.skippedCount ? `${r.skippedCount} skipped` : undefined,
      });
      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">
          <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} />}
          loading={loadPassed.isPending}
          disabled={rows.length === 0}
          onClick={autoLoad}
        >
          Auto Load Ready Items
        </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 EXPORT items with inspection PASSED waiting to be loaded.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1600}>
          <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>Booking ID</Table.Th>
                <Table.Th>Customer ID</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) => (
                <Table.Tr key={r.id}>
                  <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>
                    <Text size="xs" c="dimmed">{r.bookingId ? `${r.bookingId.slice(0, 8)}…` : '—'}</Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="xs" c="dimmed">{r.customerId ? `${r.customerId.slice(0, 8)}…` : '—'}</Text>
                  </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>
                    <Badge color="teal" variant="light" size="sm">
                      {r.status}
                    </Badge>
                  </Table.Td>
                </Table.Tr>
              ))}
            </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 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: r.skippedCount ? `${r.skippedCount} skipped` : undefined,
      });
      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={() => 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={() => 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={1600}>
          <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>Booking Ref</Table.Th>
                <Table.Th>Booking ID</Table.Th>
                <Table.Th>Customer ID</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>
                {dispatchable && <Table.Th ta="right">Actions</Table.Th>}
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {rows.map((r: ReadyToLoadRow) => (
                <Table.Tr key={r.id}>
                  {dispatchable && (
                    <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>
                    <Text size="xs" c="dimmed">{r.bookingId ? `${r.bookingId.slice(0, 8)}…` : '—'}</Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="xs" c="dimmed">{r.customerId ? `${r.customerId.slice(0, 8)}…` : '—'}</Text>
                  </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="blue" variant="light" size="sm">
                      {r.status}
                    </Badge>
                  </Table.Td>
                  {dispatchable && (
                    <Table.Td ta="right">
                      <Button
                        size="compact-xs"
                        variant="light"
                        color="green"
                        loading={bulkDispatch.isPending}
                        onClick={() => dispatch([r.id])}
                      >
                        Dispatch
                      </Button>
                    </Table.Td>
                  )}
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </Stack>
  );
}

/** Assigned bookings/items for an arrived import train (read-only detail view). */
function ImportTrainDetailTable({ scheduleId }: { scheduleId: string }) {
  const { data: items = [], isLoading } = useQuery(
    api.warehouses.importTrainItems.queryOptions({
      input: { scheduleId },
      enabled: Boolean(scheduleId),
    }),
  );

  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>Booking ID</Table.Th>
          <Table.Th>Booking Ref</Table.Th>
          <Table.Th>Customer ID</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>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) => (
          <Table.Tr key={it.bookingId}>
            <Table.Td>
              <Text size="xs" c="dimmed">{it.bookingId.slice(0, 8)}…</Text>
            </Table.Td>
            <Table.Td>
              <Text size="xs" fw={600}>{it.bookingReference ?? '—'}</Text>
            </Table.Td>
            <Table.Td>
              <Text size="xs" c="dimmed">{it.customerId ? `${it.customerId.slice(0, 8)}…` : '—'}</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>
              <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. */
function ImportArriveQueueTab({
  enabled,
  onChanged,
}: {
  enabled: boolean;
  onChanged?: () => void;
}) {
  const { toast } = useToast();
  const { data: trains = [], isLoading } = useQuery(
    api.warehouses.importArriveQueue.queryOptions({ enabled }),
  );
  const autoUnloadMutation = useMutation(
    api.warehouses.autoUnloadArrivedBookings.mutationOptions(),
  );
  const [openId, setOpenId] = useState<string | null>(null);
  const [busyId, setBusyId] = useState<string | null>(null);

  const autoUnload = async (train: ImportTrain) => {
    setBusyId(train.scheduleId);
    try {
      const r = await autoUnloadMutation.mutateAsync(train.scheduleId);
      const extra = [
        r.skippedCount ? `${r.skippedCount} skipped` : '',
        r.failedCount ? `${r.failedCount} failed` : '',
      ]
        .filter(Boolean)
        .join(', ');
      toast({
        title: `${r.unloadedCount} unloaded`,
        description: 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;
                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>
                        <Badge color="indigo" variant="light" size="sm">{t.status}</Badge>
                      </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="indigo"
                            leftSection={<Truck size={14} />}
                            loading={busyId === t.scheduleId}
                            onClick={() => autoUnload(t)}
                          >
                            Auto Unload Arrived Bookings
                          </Button>
                        </Group>
                      </Table.Td>
                    </Table.Tr>
                    {isOpen && (
                      <Table.Tr>
                        <Table.Td colSpan={11} bg="var(--mantine-color-gray-0)">
                          <ImportTrainDetailTable scheduleId={t.scheduleId} />
                        </Table.Td>
                      </Table.Tr>
                    )}
                  </Fragment>
                );
              })}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </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 { data: rows = [], isLoading } = useQuery(
    api.warehouses.importUnloadedQueue.queryOptions({ enabled }),
  );
  const inspectMutation = useMutation(
    api.warehouses.bulkMarkInspected.mutationOptions(),
  );
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [inspectId, setInspectId] = useState<string | 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: r.skippedCount ? `${r.skippedCount} skipped` : undefined,
      });
      setSelected(new Set());
    } 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> / {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={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={2000}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                <Table.Th w={40}>
                  <Checkbox
                    aria-label="Select all"
                    checked={allSelected}
                    indeterminate={someSelected}
                    onChange={() => (allSelected ? unselectAll() : selectAll())}
                  />
                </Table.Th>
                <Table.Th>Booking ID</Table.Th>
                <Table.Th>Booking Ref</Table.Th>
                <Table.Th>Customer ID</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) => (
                <Table.Tr key={r.id}>
                  <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="xs" c="dimmed">{r.bookingId ? `${r.bookingId.slice(0, 8)}…` : '—'}</Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" fw={600}>{r.bookingReference ?? '—'}</Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="xs" c="dimmed">{r.customerId ? `${r.customerId.slice(0, 8)}…` : '—'}</Text>
                  </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>
                    <Badge color="indigo" variant="light" size="sm">{r.currentStatus}</Badge>
                  </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>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}

      <InspectionReportModal
        opened={Boolean(inspectId)}
        onClose={() => setInspectId(null)}
        inventoryId={inspectId}
      />
    </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>
  );
}

/** New bulk Receive: Import / Export tabs with eligible PAID bookings. */
function BulkReceiveModal({ opened, onClose, onReceived }: ReceiveInventoryModalProps) {
  const [location, setLocation] = useState<Location>({ warehouseId: '', yardId: '', zoneId: '' });
  const [tab, setTab] = useState<'IMPORT' | 'EXPORT'>('IMPORT');

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

  return (
    <Modal opened={opened} onClose={onClose} title="Receive at warehouse" centered size="80rem">
      <Stack gap="md">
        <LocationSelects value={location} onChange={setLocation} />

        <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">
            <Tabs defaultValue="arrive-queue" mt="xs">
              <Tabs.List>
                <Tabs.Tab value="arrive-queue" leftSection={<Train size={14} />}>
                  Arrive Queue
                </Tabs.Tab>
                <Tabs.Tab value="unloaded-queue">Unloaded Queue</Tabs.Tab>
                <Tabs.Tab value="dispatch-queue">Dispatch Queue</Tabs.Tab>
              </Tabs.List>

              <Tabs.Panel value="arrive-queue">
                <ImportArriveQueueTab enabled={opened} onChanged={onReceived} />
              </Tabs.Panel>
              <Tabs.Panel value="unloaded-queue">
                <ImportUnloadedQueueTab enabled={opened} />
              </Tabs.Panel>
              <Tabs.Panel value="dispatch-queue">
                <ImportDispatchQueueTab enabled={opened} />
              </Tabs.Panel>
            </Tabs>
          </Tabs.Panel>
          <Tabs.Panel value="EXPORT">
            <Tabs defaultValue="receive-queue" mt="xs">
              <Tabs.List>
                <Tabs.Tab value="receive-queue">Receive Queue</Tabs.Tab>
                <Tabs.Tab value="ready-to-load">Ready To Load</Tabs.Tab>
                <Tabs.Tab value="loaded">Loaded</Tabs.Tab>
                <Tabs.Tab value="dispatch-queue">Dispatch Queue</Tabs.Tab>
              </Tabs.List>

              <Tabs.Panel value="receive-queue">
                <EligibleTab direction="EXPORT" location={location} enabled={opened} onChanged={onReceived} />
              </Tabs.Panel>
              <Tabs.Panel value="ready-to-load">
                <ReadyToLoadTab enabled={opened} onChanged={onReceived} />
              </Tabs.Panel>
              <Tabs.Panel value="loaded">
                <LoadedExportTab enabled={opened} dispatchable={false} onChanged={onReceived} />
              </Tabs.Panel>
              <Tabs.Panel value="dispatch-queue">
                <LoadedExportTab enabled={opened} dispatchable onChanged={onReceived} />
              </Tabs.Panel>
            </Tabs>
          </Tabs.Panel>
        </Tabs>

        <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: '',
  });

  useEffect(() => {
    if (opened) {
      setSelectedBooking(bookingId ?? '');
      setForm({ warehouseId: '', yardId: '', zoneId: '', quantity: '', weight: '', volume: '', notes: '' });
    }
  }, [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 (form.quantity === '' || form.weight === '') {
      toast({ variant: 'destructive', title: 'Quantity and weight are required' });
      return;
    }
    const payload: ReceiveInventoryPayload = {
      bookingId: selectedBooking.trim(),
      warehouseId: form.warehouseId,
      yardId: form.yardId,
      zoneId: form.zoneId,
      quantity: Number(form.quantity),
      weight: Number(form.weight),
      volume: form.volume === '' ? undefined : Number(form.volume),
      notes: form.notes.trim() || undefined,
    };
    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 }))} />

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

        <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
          </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 ? <SingleBookingReceiveModal {...props} /> : <BulkReceiveModal {...props} />;
}
