import {
  Alert,
  Badge,
  Button,
  Checkbox,
  Group,
  Loader,
  Modal,
  Select,
  Stack,
  Table,
  Tabs,
  Text,
  Tooltip,
} from '@mantine/core';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { FileText } from 'lucide-react';
import { useMemo, useState } from 'react';

import { useToast } from '@/hooks/use-toast';
import {
  warehouseService,
  type ContainerItem,
  type ContainerItemStage,
} from '@/services/warehouse.service';
import { extractDownloadErrorMessage, extractErrorMessage } from './options';
import { openPdfBlob } from './pdf';

interface ContainerItemsModalProps {
  opened: boolean;
  onClose: () => void;
  bookingId: string | null;
  bookingReference?: string | null;
}

const STAGE_TABS: Array<{ value: string; label: string }> = [
  { value: 'ALL', label: 'All' },
  { value: 'RECEIVED', label: 'Received' },
  { value: 'GRN', label: "GRN'd" },
  { value: 'ASSIGNED', label: 'Assigned' },
  { value: 'LOADED', label: 'Loaded' },
  { value: 'LEFT', label: 'Left' },
  { value: 'DELIVERED', label: 'Delivered' },
];

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

/** Loadable = not yet loaded (PENDING/RECEIVED/GRN, or customer-ASSIGNED awaiting load). */
const isLoadable = (i: ContainerItem) =>
  i.stage === 'PENDING' || i.stage === 'RECEIVED' || i.stage === 'GRN' || i.stage === 'ASSIGNED';

export function ContainerItemsModal({ opened, onClose, bookingId, bookingReference }: ContainerItemsModalProps) {
  const { toast } = useToast();
  const queryClient = useQueryClient();
  const [tab, setTab] = useState('ALL');
  const [selected, setSelected] = useState<string[]>([]);
  const [truckId, setTruckId] = useState<string | null>(null);

  const itemsKey = ['container-items', bookingId];
  const { data: items = [], isLoading } = useQuery({
    queryKey: itemsKey,
    queryFn: () => warehouseService.getContainerItems(bookingId as string),
    enabled: opened && Boolean(bookingId),
  });
  const { data: trucks = [] } = useQuery({
    queryKey: ['ci-trucks', bookingId],
    queryFn: () => warehouseService.getCustomerTrucks(bookingId as string),
    enabled: opened && Boolean(bookingId),
  });

  const visible = useMemo(
    () => (tab === 'ALL' ? items : items.filter((i) => i.stage === tab)),
    [items, tab],
  );
  // Any assigned, not-yet-departed truck can be loaded here — loading a truck at
  // the warehouse auto-marks it arrived on the backend, so assigned-but-not-yet-
  // arrived trucks are selectable too (labelled "assigned" until they arrive).
  const truckOptions = trucks
    .filter((t) => !(t as { departedAt?: string }).departedAt)
    .map((t) => ({
      value: t.id,
      label: `${t.plateNumber} · ${t.driverName}${
        (t as { arrivedAt?: string }).arrivedAt ? '' : ' (assigned)'
      }`,
    }));

  const loadMutation = useMutation({
    mutationFn: () => warehouseService.loadTruck(bookingId as string, truckId as string, selected),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: itemsKey });
      setSelected([]);
      toast({ title: 'Containers loaded onto truck' });
    },
    onError: (e) => toast({ variant: 'destructive', title: 'Load failed', description: extractErrorMessage(e) }),
  });

  const requestSign = async () => {
    try {
      const res = await warehouseService.requestHandoverSignature(bookingId as string);
      queryClient.invalidateQueries({ queryKey: itemsKey });
      if (res.alreadySigned) {
        toast({ title: 'Handover already signed', description: 'You can generate the exit paper now.' });
      } else {
        toast({
          title: 'Handover not signed',
          description: `Signature request sent to the customer${res.reference ? ` (${res.reference})` : ''}.`,
        });
      }
    } catch (e) {
      toast({ variant: 'destructive', title: 'Could not request signature', description: extractErrorMessage(e) });
    }
  };

  const openExitPaper = async (assignmentId: string, plate: string) => {
    try {
      const res = await warehouseService.downloadTruckExitPaper(assignmentId);
      openPdfBlob(res.data, `exit-${plate}.pdf`);
    } catch (e) {
      toast({ variant: 'destructive', title: 'Exit paper not ready', description: await extractDownloadErrorMessage(e) });
    }
  };

  const is40 = (n: string) =>
    (items.find((i) => i.containerNumber === n)?.containerSize ?? '').includes('40');

  // A truck carries at most 2 containers, and a 40ft fills the truck (max 1).
  const toggle = (n: string) =>
    setSelected((s) => {
      if (s.includes(n)) return s.filter((x) => x !== n);
      const next = [...s, n];
      if (next.length > 2) {
        toast({ variant: 'destructive', title: 'A truck carries at most 2 containers' });
        return s;
      }
      if (next.length > 1 && next.some(is40)) {
        toast({
          variant: 'destructive',
          title: 'A 40ft container fills the truck',
          description: 'Load only one 40ft container per truck.',
        });
        return s;
      }
      return next;
    });

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      centered
      size="90%"
      title={<Text fw={700}>Container / bulk items {bookingReference ? `· ${bookingReference}` : ''}</Text>}
    >
      <Tabs value={tab} onChange={(v) => setTab(v ?? 'ALL')} mb="sm">
        <Tabs.List>
          {STAGE_TABS.map((t) => {
            const count = t.value === 'ALL' ? items.length : items.filter((i) => i.stage === t.value).length;
            return (
              <Tabs.Tab key={t.value} value={t.value} rightSection={<Badge size="xs" variant="light">{count}</Badge>}>
                {t.label}
              </Tabs.Tab>
            );
          })}
        </Tabs.List>
      </Tabs>

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader />
        </Group>
      ) : items.length === 0 ? (
        <Alert color="gray" variant="light">No container or bulk items on this booking.</Alert>
      ) : (
        <Stack gap="sm">
          <Table.ScrollContainer minWidth={900}>
            <Table striped highlightOnHover verticalSpacing="xs">
              <Table.Thead>
                <Table.Tr>
                  <Table.Th />
                  <Table.Th>Container</Table.Th>
                  <Table.Th>Size</Table.Th>
                  <Table.Th>Goods</Table.Th>
                  <Table.Th>Stage</Table.Th>
                  <Table.Th>Truck</Table.Th>
                  <Table.Th>Booking</Table.Th>
                  <Table.Th>Contract</Table.Th>
                  <Table.Th>Last mile</Table.Th>
                  <Table.Th ta="right">Actions</Table.Th>
                </Table.Tr>
              </Table.Thead>
              <Table.Tbody>
                {visible.map((i) => (
                  <Table.Tr key={i.containerNumber}>
                    <Table.Td>
                      <Checkbox
                        checked={selected.includes(i.containerNumber)}
                        onChange={() => toggle(i.containerNumber)}
                        disabled={!isLoadable(i)}
                      />
                    </Table.Td>
                    <Table.Td><Text fw={600}>{i.containerNumber}</Text></Table.Td>
                    <Table.Td>
                      {i.containerSize ? (
                        <Badge variant="light" color={i.containerSize.includes('40') ? 'grape' : 'blue'}>
                          {i.containerSize}
                        </Badge>
                      ) : (
                        <Text c="dimmed" size="sm">bulk</Text>
                      )}
                    </Table.Td>
                    <Table.Td>{i.goods ?? '—'}</Table.Td>
                    <Table.Td><Badge color={STAGE_COLOR[i.stage]} variant="light">{i.stage}</Badge></Table.Td>
                    <Table.Td>{i.truckPlate ?? '—'}</Table.Td>
                    <Table.Td>{i.bookingReference ?? '—'}</Table.Td>
                    <Table.Td>{i.contractId ? <Badge variant="outline" color="indigo">Contract</Badge> : '—'}</Table.Td>
                    <Table.Td>{i.hasLastMile ? <Badge variant="light" color="cyan">EDR</Badge> : <Badge variant="light" color="gray">Self-haul</Badge>}</Table.Td>
                    <Table.Td ta="right">
                      {i.loaded && i.truckAssignmentId && (
                        <Tooltip
                          label="Sign the handover first — a truck can't get its exit paper until the handover is signed."
                          disabled={i.handoverSigned}
                          withArrow
                          multiline
                          w={240}
                        >
                          <Button
                            size="compact-xs"
                            variant="light"
                            color={i.handoverSigned ? 'orange' : 'gray'}
                            leftSection={<FileText size={13} />}
                            onClick={() =>
                              i.handoverSigned
                                ? openExitPaper(i.truckAssignmentId as string, i.truckPlate ?? '')
                                : requestSign()
                            }
                          >
                            Exit Paper
                          </Button>
                        </Tooltip>
                      )}
                    </Table.Td>
                  </Table.Tr>
                ))}
              </Table.Tbody>
            </Table>
          </Table.ScrollContainer>

          {/* Multiselect → load onto a truck */}
          <Group justify="space-between" align="flex-end">
            <Text size="sm" c="dimmed">
              {selected.length} selected
              {(() => {
                const pending = items.filter((i) => !i.truckAssignmentId).length;
                return pending > 0 ? ` · ${pending} container${pending === 1 ? '' : 's'} pending assignment` : '';
              })()}
            </Text>
            <Group gap="sm" align="flex-end">
              <Select
                label="Load onto truck"
                placeholder={truckOptions.length ? 'Select truck' : 'No truck assigned'}
                data={truckOptions}
                value={truckId}
                onChange={setTruckId}
                disabled={truckOptions.length === 0}
                w={260}
              />
              <Button
                color="edr-green"
                disabled={selected.length === 0 || !truckId}
                loading={loadMutation.isPending}
                onClick={() => loadMutation.mutate()}
              >
                Load selected
              </Button>
            </Group>
          </Group>
        </Stack>
      )}
    </Modal>
  );
}
