import { Alert, Badge, Button, Group, Loader, Modal, MultiSelect, Stack, Text } from '@mantine/core';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { FileText, Truck } from 'lucide-react';
import { useState } from 'react';

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

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

/**
 * Truck_dispatch: after a self-haul truck arrives, staff select which of the
 * booking's containers ride each truck. The loaded set drives the truck's gross
 * weight; the truck is weighed for real on departure.
 */
export function TruckDispatchModal({ opened, onClose, bookingId, bookingReference }: TruckDispatchModalProps) {
  const { toast } = useToast();
  const queryClient = useQueryClient();
  const [selectedByTruck, setSelectedByTruck] = useState<Record<string, string[]>>({});

  const trucksKey = ['td-customer-trucks', bookingId];
  const loadableKey = ['td-loadable', bookingId];

  const { data: trucks = [], isLoading: trucksLoading } = useQuery({
    queryKey: trucksKey,
    queryFn: () => warehouseService.getCustomerTrucks(bookingId as string),
    enabled: opened && Boolean(bookingId),
  });
  const { data: loadable = [], isLoading: loadableLoading } = useQuery({
    queryKey: loadableKey,
    queryFn: () => warehouseService.getLoadableContainers(bookingId as string),
    enabled: opened && Boolean(bookingId),
  });

  const loadMutation = useMutation({
    mutationFn: ({ assignmentId, containerNumbers }: { assignmentId: string; containerNumbers: string[] }) =>
      warehouseService.loadTruck(bookingId as string, assignmentId, containerNumbers),
    onSuccess: (_res, vars) => {
      queryClient.invalidateQueries({ queryKey: trucksKey });
      queryClient.invalidateQueries({ queryKey: loadableKey });
      setSelectedByTruck((s) => ({ ...s, [vars.assignmentId]: [] }));
      toast({ title: 'Truck loaded' });
    },
    onError: (e) => toast({ variant: 'destructive', title: 'Load failed', description: extractErrorMessage(e) }),
  });

  const openTruckExitPaper = 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) });
    }
  };

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      centered
      size="lg"
      title={
        <Group gap={8}>
          <Truck size={18} />
          <Text fw={700}>Truck_dispatch — load containers {bookingReference ? `· ${bookingReference}` : ''}</Text>
        </Group>
      }
    >
      {trucksLoading || loadableLoading ? (
        <Group justify="center" py="lg">
          <Loader />
        </Group>
      ) : trucks.length === 0 ? (
        <Alert color="orange" variant="light">
          No customer truck is assigned to this booking yet.
        </Alert>
      ) : (
        <Stack gap="md">
          {trucks.map((t) => {
            const alreadyLoaded = (t.containers ?? []).map((c) => c.containerNumber);
            // Options = still-loadable + this truck's own already-loaded (so they stay visible).
            const options = Array.from(new Set([...loadable, ...alreadyLoaded]));
            const selected = selectedByTruck[t.id] ?? alreadyLoaded;
            const departed = Boolean(t.arrivedAt) && Boolean((t as { departedAt?: string }).departedAt);
            return (
              <Stack
                key={t.id}
                gap={8}
                style={{ border: '1px solid #EEF2F6', borderRadius: 12, padding: 14 }}
              >
                <Group justify="space-between">
                  <Text fw={700}>{t.plateNumber}</Text>
                  <Group gap={6}>
                    <Text size="sm" c="dimmed">{t.driverName} · {t.truckType}</Text>
                    {t.arrivedAt ? <Badge color="green" variant="light">Arrived</Badge> : <Badge color="orange" variant="light">Not arrived</Badge>}
                  </Group>
                </Group>
                <MultiSelect
                  label="Containers on this truck"
                  placeholder="Select containers"
                  data={options}
                  value={selected}
                  onChange={(v) => setSelectedByTruck((s) => ({ ...s, [t.id]: v }))}
                  searchable
                  disabled={departed || !t.arrivedAt}
                  nothingFoundMessage="No loadable containers"
                />
                <Group justify="flex-end" gap="xs">
                  <Button
                    size="xs"
                    variant="light"
                    color="orange"
                    leftSection={<FileText size={14} />}
                    onClick={() => openTruckExitPaper(t.id, t.plateNumber)}
                  >
                    Exit Paper
                  </Button>
                  <Button
                    size="xs"
                    color="edr-green"
                    disabled={departed || !t.arrivedAt || (selectedByTruck[t.id] ?? alreadyLoaded).length === 0}
                    loading={loadMutation.isPending}
                    onClick={() =>
                      loadMutation.mutate({
                        assignmentId: t.id,
                        containerNumbers: selectedByTruck[t.id] ?? alreadyLoaded,
                      })
                    }
                  >
                    Load truck
                  </Button>
                </Group>
              </Stack>
            );
          })}
        </Stack>
      )}
    </Modal>
  );
}
