import { useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useMutation, useQuery } from "@tanstack/react-query";
import {
  Alert,
  Box,
  Button,
  Group,
  Loader,
  NumberInput,
  Paper,
  SegmentedControl,
  Stack,
  Text,
  Textarea,
  Title,
} from "@mantine/core";
import { AlertCircle, ArrowLeft, CalendarDays, Send } from "lucide-react";
import toast from "react-hot-toast";
import type { Freight } from "@edr/types";
import { DatePickerInput } from "@mantine/dates";

import { contractsService } from "@/services/contracts.service";

const BORDER = "#E6ECF2";

export default function NewShipmentRequestPage() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const [scheduledDate, setScheduledDate] = useState("");
  // Container contracts: one quantity per enabled size (e.g. 20ft + 40ft).
  const [qtyBySize, setQtyBySize] = useState<Record<string, number | string>>(
    {},
  );
  // Bulk contracts: a single amount — tons (PER_TON) or item count (PER_ITEM).
  const [bulkAmount, setBulkAmount] = useState<number | string>("");
  // GL books this shipment on the customer's behalf, so the currency they want
  // to be invoiced in has to be stated here — the contract itself quotes USD.
  const [paymentCurrency, setPaymentCurrency] = useState<"USD" | "ETB">("USD");
  const [notes, setNotes] = useState("");

  const { data: contract, isLoading } = useQuery({
    queryKey: ["contract", id],
    queryFn: () => contractsService.get(id!),
    enabled: Boolean(id),
  });

  const { data: capacity } = useQuery({
    queryKey: ["contract-capacity", id],
    queryFn: () => contractsService.getCapacity(id!),
    enabled: Boolean(id) && contract?.contractKind === "GENERAL",
  });

  const submit = useMutation({
    mutationFn: (dto: Freight.CreateBookingRequestDto) =>
      contractsService.submitBookingRequest(id!, dto),
    onSuccess: (request) => {
      // Clearance-first flow: the request auto-initiates a booking instance —
      // send the customer straight to it. The clearance service fee is due
      // first; document upload unlocks once it settles.
      if (request.createdBookingId) {
        toast.success(
          "Shipment initiated — pay the clearance service fee to unlock the document upload.",
        );
        navigate(`/bookings/${request.createdBookingId}`);
      } else {
        toast.success("Shipment request submitted");
        navigate(`/contracts/${id}`);
      }
    },
    onError: (e: Error) => toast.error(e.message || "Could not submit request"),
  });

  if (isLoading || !contract) {
    return (
      <Group justify="center" py={80}>
        <Loader color="teal" />
      </Group>
    );
  }

  const isContainer = contract.freightType === "CONTAINER";
  const route = contract.routes?.[0];
  // GENERAL customs contracts: GL schedules the shipment during clearance —
  // the customer only states the quantity (and billing currency), never a date.
  const hasCustoms =
    contract.contractKind === "GENERAL" &&
    (contract.serviceType?.includesCustoms ?? contract.customsClearingEnabled);
  const isIntercity = contract.tradeDirection === "DOMESTIC";

  // Only the container sizes the contract was scoped for (20ft, 40ft, or both).
  const SIZE_ORDER = ["20ft", "40ft"];
  const enabledSizes = SIZE_ORDER.filter((s) =>
    contract.cargoScope?.some(
      (l) => (l.containerSize ?? "").toLowerCase() === s,
    ),
  );
  // A CONTAINER contract should always carry scope lines; fall back to both.
  const sizes = enabledSizes.length ? enabledSizes : SIZE_ORDER;

  // Bulk: pick the bulk scope line and read how it's measured.
  const bulkScope =
    contract.cargoScope?.find((l) => !l.containerSize) ??
    contract.cargoScope?.[0];
  const isPerItem = bulkScope?.cargoType?.unitOfMeasure === "PER_ITEM";

  // 20ft containers ride two per wagon, so an odd total can never be planned —
  // and GL's create-booking form blocks it too, so an odd request would only
  // dead-end there. Same even-number rule the booking forms apply.
  const ft20Requested = isContainer ? Number(qtyBySize["20ft"]) || 0 : 0;
  const hasOdd20ft = ft20Requested % 2 === 1;

  const handleSubmit = () => {
    if (hasOdd20ft) return;
    const dto: Freight.CreateBookingRequestDto = {
      contractRouteId: route?.id,
      scheduledDate: hasCustoms ? undefined : scheduledDate || undefined,
      paymentCurrency: isIntercity ? "ETB" : paymentCurrency,
      notes: notes.trim() || undefined,
    };

    if (isContainer) {
      // One line per size the user filled; 0 (or blank) sizes are dropped.
      const containers = sizes
        .map((size) => ({ containerSize: size, quantity: Number(qtyBySize[size]) || 0 }))
        .filter((line) => line.quantity > 0);
      if (containers.length === 0) {
        toast.error("Enter a quantity for at least one container size");
        return;
      }
      dto.containers = containers;
    } else {
      const amount = Number(bulkAmount) || 0;
      if (amount <= 0) {
        toast.error(isPerItem ? "Enter the number of items" : "Enter the cargo weight");
        return;
      }
      dto.bulk = {
        cargoTypeId: bulkScope?.cargoTypeId ?? null,
        ...(isPerItem ? { itemCount: amount } : { cargoWeightTons: amount }),
      };
    }

    submit.mutate(dto);
  };

  return (
    <Box style={{ padding: "28px 32px 40px", maxWidth: 720, margin: "0 auto" }}>
      <Stack gap="lg">
        <Group gap="md">
          <Button variant="subtle" color="gray" onClick={() => navigate(`/contracts/${id}`)}>
            <ArrowLeft size={18} />
          </Button>
          <div>
            <Title order={3}>Request shipment</Title>
            <Text size="sm" c="dimmed">
              {contract.reference} — Global Logistics will review and create your booking.
            </Text>
          </div>
        </Group>

        <Paper withBorder radius="lg" p="xl" style={{ borderColor: BORDER }}>
          <Stack gap="md">
            {!hasCustoms && (
              <DatePickerInput
                label="Preferred shipment date"
                placeholder="Pick a date"
                leftSection={<CalendarDays size={16} />}
                minDate={new Date().toISOString().slice(0, 10)}
                value={scheduledDate || null}
                onChange={(v) => setScheduledDate(v ?? "")}
                radius="md"
                popoverProps={{ withinPortal: true }}
              />
            )}

            {isContainer ? (
              <Stack gap="sm">
                {sizes.map((size) => (
                  <NumberInput
                    key={size}
                    label={`Number of ${size} containers`}
                    value={qtyBySize[size] ?? 0}
                    onChange={(v) =>
                      setQtyBySize((prev) => ({ ...prev, [size]: v }))
                    }
                    min={0}
                    allowDecimal={false}
                  />
                ))}
                {sizes.length > 1 ? (
                  <Text size="xs" c="dimmed">
                    Enter a quantity for each size you need — leave a size at 0 if
                    you don&apos;t need it.
                  </Text>
                ) : null}
                {hasCustoms ? (
                  <Text size="xs" c="dimmed">
                    Global Logistics schedules the shipment date during customs
                    clearance — you only state the quantity.
                  </Text>
                ) : null}
              </Stack>
            ) : (
              <NumberInput
                label={isPerItem ? "Number of items" : "Cargo weight (tons)"}
                description={
                  hasCustoms
                    ? "Global Logistics schedules the shipment date during customs clearance — you only state the quantity."
                    : undefined
                }
                value={bulkAmount}
                onChange={setBulkAmount}
                min={0}
                allowDecimal={!isPerItem}
              />
            )}

            {hasOdd20ft ? (
              <Alert
                color="red"
                variant="light"
                radius="md"
                icon={<AlertCircle size={16} />}
                title={`Odd number of 20ft containers (${ft20Requested})`}
              >
                <Text fz={13}>
                  20ft containers travel two per wagon, so they must be requested
                  in even numbers. Please add one more 20ft container or remove
                  one (e.g. request {ft20Requested + 1} or {ft20Requested - 1}{" "}
                  instead of {ft20Requested}).
                </Text>
              </Alert>
            ) : null}

            {capacity?.length ? (
              <Text size="xs" c="dimmed">
                Remaining capacity is shown on the contract — GL will validate your request.
              </Text>
            ) : null}

            <Box>
              <Text size="sm" fw={600} mb={4}>
                Billing currency *
              </Text>
              <Text size="xs" c="dimmed" mb={8}>
                {isIntercity
                  ? "Intercity shipments are invoiced in ETB."
                  : "Your contract is quoted in USD. Global Logistics will book this shipment and invoice you in the currency you pick here."}
              </Text>
              <SegmentedControl
                value={isIntercity ? "ETB" : paymentCurrency}
                onChange={(v) => setPaymentCurrency(v as "USD" | "ETB")}
                disabled={isIntercity}
                data={[
                  { label: "USD", value: "USD" },
                  { label: "ETB", value: "ETB" },
                ]}
                color="teal"
                radius={10}
              />
            </Box>

            <Textarea
              label="Notes (optional)"
              value={notes}
              onChange={(e) => setNotes(e.currentTarget.value)}
              minRows={2}
            />

            <Button
              color="teal"
              leftSection={<Send size={16} />}
              loading={submit.isPending}
              onClick={handleSubmit}
              disabled={hasOdd20ft}
            >
              Submit shipment request
            </Button>
          </Stack>
        </Paper>
      </Stack>
    </Box>
  );
}
