import { useMemo } from "react";
import {
  Badge,
  Button,
  Card,
  Group,
  Paper,
  Progress,
  Select,
  SimpleGrid,
  Stack,
  Text,
  TextInput,
} from "@mantine/core";
import { CheckCircle2, Container } from "lucide-react";

import type { ContainerPlacement, ContainerUnitRow } from "@/types/trainScheduling";

import { autoFillPlacements, unitKey, validateLocalPlacements } from "./containerPlacement.util";

export function ContainerPlacementGrid({
  units,
  containerSlots,
  placements,
  onChange,
}: {
  units: ContainerUnitRow[];
  containerSlots: number[];
  placements: ContainerPlacement[];
  onChange: (placements: ContainerPlacement[]) => void;
}) {
  const placementMap = useMemo(() => {
    const map = new Map<string, ContainerPlacement>();
    for (const placement of placements) {
      map.set(unitKey(placement.bookingContainerId, placement.unitIndex), placement);
    }
    return map;
  }, [placements]);

  const issues = useMemo(() => validateLocalPlacements(units, placements), [units, placements]);

  const completedCount = useMemo(
    () =>
      units.filter((unit) => {
        const placement = placementMap.get(unitKey(unit.bookingContainerId, unit.unitIndex));
        return placement?.sequenceNo && placement.containerNumber?.trim();
      }).length,
    [units, placementMap],
  );

  const slotOptions = containerSlots.map((seq) => ({
    value: String(seq),
    label: `Wagon #${seq}`,
  }));

  const updatePlacement = (unit: ContainerUnitRow, patch: Partial<ContainerPlacement>) => {
    const key = unitKey(unit.bookingContainerId, unit.unitIndex);
    const existing = placementMap.get(key);
    const next: ContainerPlacement = {
      bookingContainerId: unit.bookingContainerId,
      unitIndex: unit.unitIndex,
      sequenceNo: existing?.sequenceNo ?? containerSlots[0] ?? 1,
      containerNumber: existing?.containerNumber,
      sealNumber: existing?.sealNumber,
      ...patch,
    };
    onChange([
      ...placements.filter(
        (p) => !(p.bookingContainerId === unit.bookingContainerId && p.unitIndex === unit.unitIndex),
      ),
      next,
    ]);
  };

  if (!units.length) {
    return (
      <Text size="sm" c="dimmed">
        No container units in this selection.
      </Text>
    );
  }

  const progress = units.length ? Math.round((completedCount / units.length) * 100) : 0;

  return (
    <Stack gap="md">
      <Paper p="md" radius="xl" withBorder>
        <Group justify="space-between" align="flex-start" wrap="wrap" gap="md">
          <Stack gap={4}>
            <Group gap="xs">
              <Container size={18} />
              <Text fw={600} size="sm">
                Container assignment
              </Text>
            </Group>
            <Text size="xs" c="dimmed">
              Map each booking unit to a wagon slot and enter the container number. One wagon fits
              either 1×40ft or 2×20ft containers.
            </Text>
          </Stack>
          <Button
            variant="light"
            size="compact-sm"
            onClick={() => onChange(autoFillPlacements(units, containerSlots))}
          >
            Auto-fill slots
          </Button>
        </Group>

        <Stack gap={6} mt="md">
          <Group justify="space-between">
            <Text size="xs" c="dimmed">
              {completedCount} of {units.length} units complete
            </Text>
            <Text size="xs" fw={500}>
              {progress}%
            </Text>
          </Group>
          <Progress
            value={progress}
            size="sm"
            radius="xl"
            color={issues.length ? "yellow" : "edr-green"}
          />
        </Stack>
      </Paper>

      {issues.length ? (
        <Stack gap={6}>
          {issues.map((issue) => (
            <Badge key={issue} color="red" variant="light" size="sm" w="fit-content">
              {issue}
            </Badge>
          ))}
        </Stack>
      ) : (
        <Badge
          color="edr-green"
          variant="light"
          size="sm"
          w="fit-content"
          leftSection={<CheckCircle2 size={12} />}
        >
          All units mapped
        </Badge>
      )}

      <SimpleGrid cols={{ base: 1, lg: 2 }} spacing="md">
        {units.map((unit) => {
          const key = unitKey(unit.bookingContainerId, unit.unitIndex);
          const placement = placementMap.get(key);
          const isComplete = placement?.sequenceNo && placement.containerNumber?.trim();

          return (
            <Card key={key} radius="xl" padding="md" withBorder>
              <Stack gap="md">
                <Group justify="space-between" align="flex-start">
                  <Stack gap={2}>
                    <Text size="sm" fw={600}>
                      {unit.bookingReference}
                    </Text>
                    <Text size="xs" c="dimmed">
                      {unit.label} · {unit.containerTypeCode} · {unit.grossWeightTons}T
                    </Text>
                  </Stack>
                  <Badge size="sm" variant="light" color={isComplete ? "edr-green" : "gray"}>
                    {isComplete ? "Ready" : "Pending"}
                  </Badge>
                </Group>

                <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="sm">
                  <Select
                    label="Wagon slot"
                    size="sm"
                    data={slotOptions}
                    value={placement?.sequenceNo ? String(placement.sequenceNo) : null}
                    onChange={(value) =>
                      updatePlacement(unit, { sequenceNo: Number(value ?? containerSlots[0]) })
                    }
                    placeholder="Select wagon"
                    searchable
                  />
                  <TextInput
                    label="Container number"
                    size="sm"
                    placeholder="e.g. MSCU1234567"
                    value={placement?.containerNumber ?? ""}
                    onChange={(e) =>
                      updatePlacement(unit, {
                        containerNumber: e.currentTarget.value,
                      })
                    }
                  />
                </SimpleGrid>
              </Stack>
            </Card>
          );
        })}
      </SimpleGrid>
    </Stack>
  );
}
