import { useMemo, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import {
  ActionIcon,
  Alert,
  Badge,
  Box,
  Button,
  Center,
  Divider,
  Grid,
  Group,
  Loader,
  NumberInput,
  Select,
  Stack,
  Text,
  Textarea,
  TextInput,
} from "@mantine/core";
import {
  Container as ContainerIcon,
  FileText,
  Package,
  Plus,
  Trash2,
} from "lucide-react";
import type { Freight } from "@edr/types";

import { PageContainer } from "@/components/page";
import { PageHeader } from "@/components/page/PageHeader";
import { SectionCard } from "@/components/bookings/detail/SectionCard";
import {
  useContractCapacity,
  useContractDetail,
  useContractMutations,
} from "@/hooks/contracts/useContracts";
import { Boxes } from "lucide-react";

interface UnitDraft {
  containerNumber: string;
  sealNumber: string;
  vgmTons: number | string;
}

interface ContainerLineDraft {
  containerSize: string;
  hazardousQuantity: number | string;
  reeferQuantity: number | string;
  units: UnitDraft[];
}

interface BulkLineDraft {
  cargoTypeId: string;
  cargoWeightTons: number | string;
  itemCount: number | string;
  hazardousQuantity: number | string;
}

function emptyUnit(): UnitDraft {
  return { containerNumber: "", sealNumber: "", vgmTons: "" };
}

export default function GlCreateBookingForm() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { data: contract, isLoading } = useContractDetail(id);
  const { data: capacity = [] } = useContractCapacity(id);
  const mutations = useContractMutations(id ?? "");

  const [scheduledDate, setScheduledDate] = useState("");
  const [contractRouteId, setContractRouteId] = useState<string | null>(null);
  const [notes, setNotes] = useState("");
  const [containerLines, setContainerLines] = useState<ContainerLineDraft[]>([]);
  const [bulkLines, setBulkLines] = useState<BulkLineDraft[]>([]);

  const isContainer = contract?.freightType === "CONTAINER";
  const routes = useMemo(
    () =>
      [...(contract?.routes ?? [])].sort((a, b) => a.sortOrder - b.sortOrder),
    [contract?.routes],
  );
  const needsRouteSelect = contract?.contractKind === "GENERAL" && routes.length > 1;

  const containerSizes = useMemo(() => {
    const sizes = new Set<string>();
    (contract?.cargoScope ?? []).forEach((s) => {
      if (s.containerSize) sizes.add(s.containerSize);
    });
    return [...sizes];
  }, [contract?.cargoScope]);

  if (isLoading) {
    return (
      <PageContainer>
        <Center mih="50vh">
          <Loader color="gray" />
        </Center>
      </PageContainer>
    );
  }

  if (!contract) {
    return (
      <PageContainer>
        <PageHeader
          title="Contract not found"
          backTo="/dashboard/contracts/clearance"
        />
      </PageContainer>
    );
  }

  // ── Container line helpers ──
  const addContainerLine = () =>
    setContainerLines((prev) => [
      ...prev,
      {
        containerSize: containerSizes[0] ?? "20ft",
        hazardousQuantity: "",
        reeferQuantity: "",
        units: [emptyUnit()],
      },
    ]);
  const removeContainerLine = (idx: number) =>
    setContainerLines((prev) => prev.filter((_, i) => i !== idx));
  const patchLine = (idx: number, patch: Partial<ContainerLineDraft>) =>
    setContainerLines((prev) =>
      prev.map((l, i) => (i === idx ? { ...l, ...patch } : l)),
    );
  const addUnit = (lineIdx: number) =>
    patchLine(lineIdx, {
      units: [...containerLines[lineIdx].units, emptyUnit()],
    });
  const removeUnit = (lineIdx: number, unitIdx: number) =>
    patchLine(lineIdx, {
      units: containerLines[lineIdx].units.filter((_, i) => i !== unitIdx),
    });
  const patchUnit = (
    lineIdx: number,
    unitIdx: number,
    patch: Partial<UnitDraft>,
  ) =>
    patchLine(lineIdx, {
      units: containerLines[lineIdx].units.map((u, i) =>
        i === unitIdx ? { ...u, ...patch } : u,
      ),
    });

  // ── Bulk line helpers ──
  const addBulkLine = () =>
    setBulkLines((prev) => [
      ...prev,
      { cargoTypeId: "", cargoWeightTons: "", itemCount: "", hazardousQuantity: "" },
    ]);
  const removeBulkLine = (idx: number) =>
    setBulkLines((prev) => prev.filter((_, i) => i !== idx));
  const patchBulk = (idx: number, patch: Partial<BulkLineDraft>) =>
    setBulkLines((prev) =>
      prev.map((l, i) => (i === idx ? { ...l, ...patch } : l)),
    );

  const canSubmit =
    Boolean(scheduledDate) &&
    (!needsRouteSelect || Boolean(contractRouteId)) &&
    (isContainer ? containerLines.length > 0 : bulkLines.length > 0);

  const handleSubmit = () => {
    if (!scheduledDate) return;

    const payload: Freight.CreateBookingUnderContractDto = {
      scheduledDate,
      ...(contractRouteId ? { contractRouteId } : {}),
      ...(notes.trim() ? { notes: notes.trim() } : {}),
    };

    if (isContainer) {
      payload.containers = containerLines.map((l) => ({
        containerSize: l.containerSize,
        quantity: l.units.length,
        ...(l.hazardousQuantity !== ""
          ? { hazardousQuantity: Number(l.hazardousQuantity) }
          : {}),
        ...(l.reeferQuantity !== ""
          ? { reeferQuantity: Number(l.reeferQuantity) }
          : {}),
        units: l.units.map((u) => ({
          containerNumber: u.containerNumber,
          ...(u.sealNumber ? { sealNumber: u.sealNumber } : {}),
          vgmTons: Number(u.vgmTons) || 0,
        })),
      }));
    } else {
      payload.bulkLines = bulkLines.map((l) => ({
        ...(l.cargoTypeId ? { cargoTypeId: l.cargoTypeId } : {}),
        ...(l.cargoWeightTons !== ""
          ? { cargoWeightTons: Number(l.cargoWeightTons) }
          : {}),
        ...(l.itemCount !== "" ? { itemCount: Number(l.itemCount) } : {}),
        ...(l.hazardousQuantity !== ""
          ? { hazardousQuantity: Number(l.hazardousQuantity) }
          : {}),
      }));
    }

    mutations.createBooking.mutate(payload, {
      onSuccess: (booking) =>
        navigate(`/dashboard/bookings/${booking.id}/milestones`),
    });
  };

  return (
    <PageContainer>
      <PageHeader
        title="Create booking (GL)"
        subtitle={`Enter the shipment details on behalf of the customer for contract ${contract.reference}.`}
        backTo={`/dashboard/contracts/clearance/${contract.id}`}
        breadcrumbs={[
          { label: "Contract Clearance", href: "/dashboard/contracts/clearance" },
          {
            label: contract.reference,
            href: `/dashboard/contracts/clearance/${contract.id}`,
          },
          { label: "Create booking" },
        ]}
      />

      <Stack gap="lg">
        {capacity.length > 0 && (
          <Alert
            color={capacity.every((c) => c.remaining === 0) ? "red" : "blue"}
            variant="light"
            radius="md"
            icon={<Boxes size={16} />}
            title="Contract draw-down capacity"
          >
            <Group gap={8} wrap="wrap">
              {capacity.map((c, i) => (
                <Badge
                  key={i}
                  color={c.remaining === 0 ? "red" : "blue"}
                  variant="light"
                  radius="sm"
                >
                  {c.containerSize ?? "Bulk"}: {c.remaining} of {c.cap} left
                </Badge>
              ))}
            </Group>
          </Alert>
        )}
        <SectionCard icon={FileText} title="Schedule">
          <Grid gap="md">
            <Grid.Col span={{ base: 12, sm: 6 }}>
              <TextInput
                label="Scheduled date"
                type="date"
                description="Binding shipment day"
                value={scheduledDate}
                onChange={(e) => setScheduledDate(e.currentTarget.value)}
                required
              />
            </Grid.Col>
            {needsRouteSelect && (
              <Grid.Col span={{ base: 12, sm: 6 }}>
                <Select
                  label="Route"
                  placeholder="Select contract route"
                  value={contractRouteId}
                  onChange={setContractRouteId}
                  data={routes.map((r) => ({
                    value: r.id,
                    label: `${r.originYard?.label ?? r.originYard?.code ?? "Origin"} → ${
                      r.destinationYard?.label ??
                      r.destinationYard?.code ??
                      "Destination"
                    }`,
                  }))}
                  required
                />
              </Grid.Col>
            )}
          </Grid>
        </SectionCard>

        {isContainer ? (
          <SectionCard
            icon={ContainerIcon}
            title="Containers"
            extra={
              <Button
                size="compact-sm"
                variant="light"
                color="edr-green"
                leftSection={<Plus size={14} />}
                onClick={addContainerLine}
              >
                Add line
              </Button>
            }
          >
            {containerLines.length === 0 ? (
              <Text size="sm" c="dimmed">
                Add at least one container line.
              </Text>
            ) : (
              <Stack gap="lg">
                {containerLines.map((line, lineIdx) => (
                  <Box
                    key={lineIdx}
                    p="md"
                    style={{
                      borderRadius: 10,
                      border: "1px solid var(--mantine-color-gray-2)",
                    }}
                  >
                    <Group justify="space-between" mb="sm">
                      <Text fw={600} size="sm">
                        Line {lineIdx + 1}
                      </Text>
                      <ActionIcon
                        variant="subtle"
                        color="red"
                        onClick={() => removeContainerLine(lineIdx)}
                        aria-label="Remove line"
                      >
                        <Trash2 size={16} />
                      </ActionIcon>
                    </Group>
                    <Grid gap="sm">
                      <Grid.Col span={{ base: 12, sm: 4 }}>
                        <Select
                          label="Container size"
                          value={line.containerSize}
                          onChange={(v) =>
                            patchLine(lineIdx, {
                              containerSize: v ?? line.containerSize,
                            })
                          }
                          data={
                            containerSizes.length > 0
                              ? containerSizes
                              : ["20ft", "40ft"]
                          }
                        />
                      </Grid.Col>
                      <Grid.Col span={{ base: 6, sm: 4 }}>
                        <NumberInput
                          label="Hazard qty"
                          min={0}
                          value={line.hazardousQuantity}
                          onChange={(v) =>
                            patchLine(lineIdx, { hazardousQuantity: v })
                          }
                        />
                      </Grid.Col>
                      <Grid.Col span={{ base: 6, sm: 4 }}>
                        <NumberInput
                          label="Reefer qty"
                          min={0}
                          value={line.reeferQuantity}
                          onChange={(v) =>
                            patchLine(lineIdx, { reeferQuantity: v })
                          }
                        />
                      </Grid.Col>
                    </Grid>

                    <Divider
                      my="sm"
                      label={`${line.units.length} container unit${
                        line.units.length === 1 ? "" : "s"
                      }`}
                      labelPosition="left"
                    />

                    <Stack gap="xs">
                      {line.units.map((unit, unitIdx) => (
                        <Grid key={unitIdx} gap="xs" align="flex-end">
                          <Grid.Col span={{ base: 12, sm: 4 }}>
                            <TextInput
                              label={unitIdx === 0 ? "Container no." : undefined}
                              placeholder="MSKU1234567"
                              value={unit.containerNumber}
                              onChange={(e) =>
                                patchUnit(lineIdx, unitIdx, {
                                  containerNumber: e.currentTarget.value,
                                })
                              }
                            />
                          </Grid.Col>
                          <Grid.Col span={{ base: 6, sm: 3 }}>
                            <TextInput
                              label={unitIdx === 0 ? "Seal no." : undefined}
                              placeholder="Optional"
                              value={unit.sealNumber}
                              onChange={(e) =>
                                patchUnit(lineIdx, unitIdx, {
                                  sealNumber: e.currentTarget.value,
                                })
                              }
                            />
                          </Grid.Col>
                          <Grid.Col span={{ base: 5, sm: 3 }}>
                            <NumberInput
                              label={unitIdx === 0 ? "VGM (t)" : undefined}
                              min={0}
                              decimalScale={2}
                              value={unit.vgmTons}
                              onChange={(v) =>
                                patchUnit(lineIdx, unitIdx, { vgmTons: v })
                              }
                            />
                          </Grid.Col>
                          <Grid.Col span={{ base: 1, sm: 2 }}>
                            <ActionIcon
                              variant="subtle"
                              color="red"
                              disabled={line.units.length === 1}
                              onClick={() => removeUnit(lineIdx, unitIdx)}
                              aria-label="Remove unit"
                            >
                              <Trash2 size={15} />
                            </ActionIcon>
                          </Grid.Col>
                        </Grid>
                      ))}
                      <Button
                        size="compact-xs"
                        variant="subtle"
                        color="edr-green"
                        leftSection={<Plus size={13} />}
                        onClick={() => addUnit(lineIdx)}
                        style={{ alignSelf: "flex-start" }}
                      >
                        Add container unit
                      </Button>
                    </Stack>
                  </Box>
                ))}
              </Stack>
            )}
          </SectionCard>
        ) : (
          <SectionCard
            icon={Package}
            title="Bulk cargo"
            extra={
              <Button
                size="compact-sm"
                variant="light"
                color="edr-green"
                leftSection={<Plus size={14} />}
                onClick={addBulkLine}
              >
                Add line
              </Button>
            }
          >
            {bulkLines.length === 0 ? (
              <Text size="sm" c="dimmed">
                Add at least one bulk line.
              </Text>
            ) : (
              <Stack gap="md">
                {bulkLines.map((line, idx) => (
                  <Box
                    key={idx}
                    p="md"
                    style={{
                      borderRadius: 10,
                      border: "1px solid var(--mantine-color-gray-2)",
                    }}
                  >
                    <Group justify="space-between" mb="sm">
                      <Text fw={600} size="sm">
                        Line {idx + 1}
                      </Text>
                      <ActionIcon
                        variant="subtle"
                        color="red"
                        onClick={() => removeBulkLine(idx)}
                        aria-label="Remove line"
                      >
                        <Trash2 size={16} />
                      </ActionIcon>
                    </Group>
                    <Grid gap="sm">
                      <Grid.Col span={{ base: 12, sm: 6 }}>
                        <TextInput
                          label="Cargo type id"
                          placeholder="Optional"
                          value={line.cargoTypeId}
                          onChange={(e) =>
                            patchBulk(idx, { cargoTypeId: e.currentTarget.value })
                          }
                        />
                      </Grid.Col>
                      <Grid.Col span={{ base: 6, sm: 6 }}>
                        <NumberInput
                          label="Weight (tons)"
                          min={0}
                          decimalScale={2}
                          value={line.cargoWeightTons}
                          onChange={(v) =>
                            patchBulk(idx, { cargoWeightTons: v })
                          }
                        />
                      </Grid.Col>
                      <Grid.Col span={{ base: 6, sm: 6 }}>
                        <NumberInput
                          label="Item count"
                          min={0}
                          value={line.itemCount}
                          onChange={(v) => patchBulk(idx, { itemCount: v })}
                        />
                      </Grid.Col>
                      <Grid.Col span={{ base: 6, sm: 6 }}>
                        <NumberInput
                          label="Hazard qty"
                          min={0}
                          value={line.hazardousQuantity}
                          onChange={(v) =>
                            patchBulk(idx, { hazardousQuantity: v })
                          }
                        />
                      </Grid.Col>
                    </Grid>
                  </Box>
                ))}
              </Stack>
            )}
          </SectionCard>
        )}

        <SectionCard icon={FileText} title="Notes">
          <Textarea
            placeholder="Internal GL notes (optional)"
            autosize
            minRows={2}
            value={notes}
            onChange={(e) => setNotes(e.currentTarget.value)}
          />
        </SectionCard>

        <Group justify="flex-end">
          <Button
            variant="default"
            onClick={() =>
              navigate(`/dashboard/contracts/clearance/${contract.id}`)
            }
          >
            Cancel
          </Button>
          <Button
            color="edr-green"
            disabled={!canSubmit}
            loading={mutations.createBooking.isPending}
            onClick={handleSubmit}
          >
            Create booking
          </Button>
        </Group>
      </Stack>
    </PageContainer>
  );
}
