import { api } from "@/services/api";
import { Freight } from "@edr/types";
import type {
  CreateBookingPayload,
  GeneratePriceResponse,
  SubmitBookingResponse,
} from "@/services/bookings.service";
import { zodResolver } from "@hookform/resolvers/zod";
import {
  Alert,
  Box,
  Button,
  Group,
  Modal,
  Stack,
  Text,
  TextInput,
  Title,
} from "@mantine/core";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  AlertCircle,
  Check,
  ChevronLeft,
  ChevronRight,
  Link2,
  Send,
  XCircle,
} from "lucide-react";
import { useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import useAuth from "@/hooks/useAuth";
import {
  BookingFormInputValues,
  STEPS,
  allowedOperationsForProfiles,
  bookingFormSchema,
  getRouteDirection,
  initialBookingFormValues,
  operationToProfileType,
  stepFields,
  type BookingDocuments,
  type BookingFormValues,
  type OperationType,
} from "./new-booking-form/schema";
import { StepIndicator } from "./new-booking-form/StepIndicator";
import {
  Step0OperationType,
  Step1ContractType,
  Step2ServiceType,
  Step4Route,
  Step5CargoDetails,
  Step8Review,
  StepDocuments,
  StepScheduling,
} from "./new-booking-form/steps";

type PriceModalMode = "submit" | "draft";

export default function NewBookingPage() {
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const [step, setStep] = useState(0);
  const auth = useAuth();
  const { data: referenceData, isLoading: refDataLoading } = useQuery(
    api.bookings.referenceData.queryOptions(),
  );

  if (!auth.isPending && !auth.company) {
    return (
      <Box
        style={{
          padding: "28px",
          minHeight: "calc(100dvh - var(--app-shell-header-height, 56px))",
          display: "flex",
          flexDirection: "column",
          justifyContent: "center",
          alignItems: "center",
        }}
      >
        <Alert
          color="orange"
          icon={<AlertCircle size={20} />}
          radius="md"
          style={{ maxWidth: "500px" }}
          mb="lg"
        >
          <Text size="lg" fw={600} mb="md">
            Complete Your Company Setup
          </Text>
          <Text size="sm" mb="md">
            You need to complete your company onboarding before you can create
            bookings. Please follow the onboarding process to get started.
          </Text>
          <Button color="orange" onClick={() => navigate("/settings")} mt="md">
            Go to Onboarding
          </Button>
        </Alert>
      </Box>
    );
  }

  if (!auth.isPending && auth.companyStatus === "pending") {
    return (
      <Box
        style={{
          padding: "28px",
          minHeight: "calc(100dvh - var(--app-shell-header-height, 56px))",
          display: "flex",
          flexDirection: "column",
          justifyContent: "center",
          alignItems: "center",
        }}
      >
        <Alert
          color="orange"
          icon={<AlertCircle size={20} />}
          radius="md"
          style={{ maxWidth: "500px" }}
          mb="lg"
        >
          <Text size="lg" fw={600} mb="md">
            Awaiting Approval
          </Text>
          <Text size="sm" mb="md">
            Your company is awaiting EDR approval. Creating bookings is disabled
            until your company has been approved.
          </Text>
          <Button color="orange" onClick={() => navigate("/bookings")} mt="md">
            Back to Bookings
          </Button>
        </Alert>
      </Box>
    );
  }

  const persistAndPriceMutation = useMutation({
    mutationFn: async ({
      payload,
      mode,
      existingBookingId,
    }: {
      payload: CreateBookingPayload;
      mode: PriceModalMode;
      existingBookingId: string | null;
    }) => {
      const documents = (form.getValues("documents") ?? {}) as BookingDocuments;
      let bookingId = existingBookingId;

      if (bookingId) {
        await api.bookings.update.call({ id: bookingId, dto: payload, documents });
      } else {
        const booking = await api.bookings.create.call({ payload, documents });
        bookingId = booking.id;
      }

      const pricing = await api.bookings.generatePrice.call({ id: bookingId });
      return { bookingId, pricing, mode };
    },
    onSuccess: ({ bookingId, pricing, mode }) => {
      setPriceBookingId(bookingId);
      setPricingData(pricing);
      setPriceModalMode(mode);
      queryClient.invalidateQueries({ queryKey: api.bookings.list.queryKey() });
    },
  });

  const confirmMutation = useMutation({
    mutationFn: async () => {
      if (!priceBookingId) throw new Error("No booking to confirm");
      return api.bookings.submit.call({ id: priceBookingId });
    },
    onSuccess: (result) => {
      if (result.priceChanged) {
        setPriceChangeResult(result);
        return;
      }
      setPriceModalMode(null);
      queryClient.invalidateQueries({ queryKey: api.bookings.list.queryKey() });
      // A partial-wagon booking is parked until a partner is found — explain the
      // wait in a modal before sending the customer to the detail page.
      if (result.status === "PENDING_CONSOLIDATION") {
        setConsolidationPending(true);
        return;
      }
      navigate(`/bookings/${priceBookingId}`);
    },
  });

  const confirmSubmitMutation = useMutation({
    mutationFn: async () => {
      if (!priceBookingId) throw new Error("No booking to confirm");
      return api.bookings.confirmSubmit.call({ id: priceBookingId });
    },
    onSuccess: (result) => {
      setPriceChangeResult(null);
      setPriceModalMode(null);
      queryClient.invalidateQueries({ queryKey: api.bookings.list.queryKey() });
      if (result.status === "PENDING_CONSOLIDATION") {
        setConsolidationPending(true);
        return;
      }
      navigate(`/bookings/${priceBookingId}`);
    },
  });

  // Customer rejects the priced booking → it becomes REJECTED (terminal) and the
  // customer starts a fresh booking.
  const rejectMutation = useMutation({
    mutationFn: async () => {
      if (!priceBookingId) throw new Error("No booking to reject");
      return api.bookings.reject.call({ id: priceBookingId });
    },
    onSuccess: () => {
      setPriceModalMode(null);
      queryClient.invalidateQueries({ queryKey: api.bookings.list.queryKey() });
      navigate("/bookings");
    },
  });

  const abortMutation = useMutation({
    mutationFn: async (reason: string) => {
      if (!priceBookingId) throw new Error("No booking to abort");
      await api.bookings.cancel.call({ id: priceBookingId, reason });
    },
    onSuccess: () => {
      setCancelDialogOpen(false);
      navigate("/bookings");
    },
  });

  const form = useForm<BookingFormInputValues, any, BookingFormValues>({
    defaultValues: initialBookingFormValues,
    resolver: zodResolver(bookingFormSchema),
    mode: "onChange",
  });

  const originYard = form.watch("originYard");
  const destinationYard = form.watch("destinationYard");
  const bookingType = form.watch("bookingType");
  const isGeneralContract = bookingType === "general_contract";

  // General contracts have no shipment date at creation — the Schedule step
  // (id 5) is skipped; the date is chosen per order against the contract later.
  const visibleSteps = useMemo(
    () => STEPS.filter((s) => !(isGeneralContract && s.id === 5)),
    [isGeneralContract],
  );
  const visibleStepIds = useMemo<number[]>(
    () => visibleSteps.map((s) => s.id),
    [visibleSteps],
  );
  const currentStepIndex = visibleStepIds.indexOf(step);
  const isLastStep = currentStepIndex === visibleStepIds.length - 1;
  const isFirstStep = currentStepIndex <= 0;
  const goToStep = (delta: number) => {
    const idx = visibleStepIds.indexOf(step);
    const nextIdx = Math.min(
      visibleStepIds.length - 1,
      Math.max(0, idx + delta),
    );
    setStep(visibleStepIds[nextIdx]);
  };

  const direction = useMemo(() => {
    const origin = referenceData?.yard.find((y) => y.id === originYard);
    const destination = referenceData?.yard.find(
      (y) => y.id === destinationYard,
    );

    const route = getRouteDirection(origin, destination);
    return route;
  }, [originYard, destinationYard]);

  // The company's onboarded profile types — drives which operations are offered
  // and which profile each operation stamps the booking to.
  const profileTypes = useMemo(
    () => (auth.company?.company?.companyProfiles ?? []).map((p) => p.type),
    [auth.company],
  );

  // Operations the customer may book, gated by the company's onboarded profiles.
  const allowedOperations = useMemo<OperationType[]>(
    () => allowedOperationsForProfiles(profileTypes),
    [profileTypes],
  );

  // Stamp the booking to the right operational profile. Import/Export (and their
  // "as FF" variants) switch the active mode so the matching onboarding documents
  // are attached; Intercity uses whatever profile is already active.
  const handleOperationSelect = (op: OperationType) => {
    if (op === "intercity") return;
    const target = operationToProfileType(op, profileTypes);
    if (auth.activeProfileType !== target) {
      void auth.switchMode(target as never);
    }
  };

  // Onboarding documents for the active profile — shown read-only in the
  // Documents step and attached to the booking on submit by the backend.
  const onboardingDocs = useMemo(() => {
    const profiles = auth.company?.company?.companyProfiles ?? [];
    const active =
      profiles.find((p) => p.id === auth.activeCompanyProfileId) ?? profiles[0];
    return active?.licenseFiles ?? [];
  }, [auth.company, auth.activeCompanyProfileId]);

  const [pricingData, setPricingData] = useState<GeneratePriceResponse | null>(
    null,
  );
  const [priceBookingId, setPriceBookingId] = useState<string | null>(null);
  const [priceModalMode, setPriceModalMode] = useState<PriceModalMode | null>(
    null,
  );
  const [priceChangeResult, setPriceChangeResult] =
    useState<SubmitBookingResponse | null>(null);
  const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
  const [cancelReason, setCancelReason] = useState("");
  // Shown when a submitted booking is parked waiting for a consolidation partner.
  const [consolidationPending, setConsolidationPending] = useState(false);

  async function handleContinue() {
    const valid = await form.trigger(stepFields[step], { shouldFocus: true });
    if (!valid) return;

    // Documents (step 6) is read-only — the active profile's onboarding files are
    // attached automatically, so there is nothing to validate here.
    goToStep(1);
  }

  function buildApiPayload(data: BookingFormValues): CreateBookingPayload {
    if (data.contractType === "renewal" && !data.previousContractRef) {
      form.setError("previousContractRef", {
        type: "manual",
        message: "Select a previous contract reference.",
      });
      setStep(1);
      throw new Error("Validation failed");
    }

    const cargoTree = referenceData?.cargo_type ?? [];
    const containerGroups = referenceData?.containers ?? [];

    const findContainerTypeId = (name: string): string => {
      for (const group of containerGroups) {
        const ct = group.types.find((t) => t.name === name);
        if (ct) return ct.id;
      }
      return "";
    };

    const cargoTypePath = data.cargoTypePath ?? [];
    const childId = cargoTypePath[1];

    const bulkChild = cargoTree
      .flatMap((g) => g.children ?? [])
      .find((c) => c.id === childId);

    // Bulk amount lives in cargoTotalWeightVgm — tons (estimated) or a whole
    // item count, depending on the commodity's unit_of_measure. Item counts are
    // rounded since fractional items are meaningless. Containers carry NO weight
    // at the wizard — VGM is captured later in operations — so container bookings
    // send 0.
    const isPerItem =
      bulkChild?.unit_of_measure === Freight.CargoUnitOfMeasure.PerItem;
    const isContract = data.bookingType === "general_contract";
    // For bulk general contracts the contracted quantity is entered against the
    // primary route in the route step; one-time bookings use the cargo-step
    // amount. Item counts are rounded since fractional items are meaningless.
    const bulkAmountRaw =
      isContract && data.cargoType === "bulk"
        ? data.primaryRouteQuantity
        : data.cargoWeight;
    const totalWeight =
      data.cargoType === "container"
        ? 0
        : isPerItem
          ? Math.round(Number(bulkAmountRaw || 0))
          : Number(bulkAmountRaw || 0);

    const cargoTypeId = data.cargoType === "bulk" ? childId : undefined;

    const cargoFreeText = bulkChild?.show_free_text_box
      ? data.cargoFreeText
      : undefined;

    const serviceType = referenceData?.service.find(
      (s) => s.id === data.serviceTypeId,
    )!;

    return {
      bookingType: isContract
        ? Freight.BookingType.GeneralContract
        : Freight.BookingType.OneTime,
      // General contracts omit the shipment date — chosen per order later.
      ...(isContract
        ? {}
        : {
            scheduledDate: data.scheduledDate
              ? new Date(data.scheduledDate).toISOString()
              : new Date().toISOString(),
          }),
      contractType:
        data.contractType.toUpperCase() as CreateBookingPayload["contractType"],
      serviceTypeId: data.serviceTypeId,
      equipmentReturn:
        data.equipmentReturn === "with_return"
          ? "WITH_RETURN"
          : "WITHOUT_RETURN",
      paymentCurrency: data.paymentCurrency,
      originYardId: data.originYard,
      destinationYardId: data.destinationYard,
      tradeDirection: direction!,
      cargoTypeId,
      // Day-level pool: the customer picks only a day (scheduledDate); the batch
      // engine assigns the train, so no trainScheduleId is sent.
      cargoTotalWeightVgm: totalWeight,
      isHazardous: data.isHazardous,
      freightType:
        data.cargoType === "container"
          ? ("CONTAINER" as const)
          : ("BULK" as const),
      containers:
        data.cargoType === "container"
          ? data.containers.map((c) => ({
            containerTypeId: findContainerTypeId(c.containerType),
            quantity: Number(c.qty || 1),
            // Weight (VGM) is not collected at the wizard — captured in operations.
            vgmPerUnitTons: 0,
          }))
          : [],
      ...(data.previousContractRef
        ? { previousContractId: data.previousContractRef }
        : {}),
      ...(data.contractType === "renewal" && data.previousContractRef
        ? { pnrCode: data.previousContractRef }
        : {}),
      ...(serviceType.includesFirstMile && data.firstMile.enabled
        ? {
            firstMilePickupAddress: data.firstMile.pickUpAddress,
            firstMilePickupLat: data.firstMile.lat ?? undefined,
            firstMilePickupLng: data.firstMile.lng ?? undefined,
          }
        : {}),
      ...(serviceType.includesLastMile && data.lastMile.enabled
        ? {
            lastMileDeliveryAddress: data.lastMile.deliveryAddress,
            lastMileDeliveryLat: data.lastMile.lat ?? undefined,
            lastMileDeliveryLng: data.lastMile.lng ?? undefined,
          }
        : {}),
      // Customs clearing: only when the service offers it and the customer opted
      // in; the agent name is required by the form in that case.
      ...(serviceType.includesCustoms && data.customsClearingEnabled
        ? {
            customsClearingEnabled: true,
            customsClearingAgent: data.customsClearingAgent,
          }
        : { customsClearingEnabled: false }),
      ...(cargoFreeText ? { cargoFreeText } : {}),
      // Multi-route general contracts: route #1 is the primary origin/destination
      // carrying the full contracted quantity; each extra route reserves its own.
      ...(isContract
        ? {
            routes: [
              {
                originYardId: data.originYard,
                destinationYardId: data.destinationYard,
                quantity:
                  data.cargoType === "container"
                    ? data.containers.reduce(
                        (sum, c) => sum + Number(c.qty || 0),
                        0,
                      )
                    : totalWeight,
              },
              ...(data.extraRoutes ?? [])
                .filter(
                  (r) =>
                    r.originYard &&
                    r.destinationYard &&
                    Number(r.quantity) > 0,
                )
                .map((r) => ({
                  originYardId: r.originYard,
                  destinationYardId: r.destinationYard,
                  quantity: Number(r.quantity),
                  ...(r.km && Number(r.km) > 0 ? { km: Number(r.km) } : {}),
                })),
            ],
          }
        : {}),
    };
  }

  const handleSaveDraft = form.handleSubmit((data) => {
    try {
      const apiPayload = buildApiPayload(data);
      persistAndPriceMutation.mutate({
        payload: apiPayload,
        mode: "draft",
        existingBookingId: priceBookingId,
      });
    } catch {
      // validation error already handled
    }
  });

  const handleSubmitBooking = form.handleSubmit((data) => {
    // Documents are reused from onboarding and attached by the backend, so there
    // is no upload requirement to enforce here.
    try {
      const apiPayload = buildApiPayload(data);
      persistAndPriceMutation.mutate({
        payload: apiPayload,
        mode: "submit",
        existingBookingId: priceBookingId,
      });
    } catch {
      // validation error already handled
    }
  });

  const isPricing =
    persistAndPriceMutation.isPending || confirmMutation.isPending;

  function closePriceModal() {
    setPriceModalMode(null);
    if (priceModalMode === "draft" && priceBookingId) {
      navigate(`/bookings/${priceBookingId}`);
    }
  }

  function handleDraftModalOk() {
    setPriceModalMode(null);
    if (priceBookingId) navigate(`/bookings/${priceBookingId}`);
  }

  return (
    <Box
      style={{
        padding: "28px 0 0",
        minHeight: "calc(100dvh - var(--app-shell-header-height, 56px))",
        display: "flex",
        flexDirection: "column",
      }}
    >
      {/* ── Page header ─────────────────────────────────────────────────── */}
      <Group
        justify="space-between"
        px="24px"
        align="flex-end"
        wrap="wrap"
        gap="md"
        mb="lg"
      >
        <Box>
          <Title
            order={1}
            fw={800}
            fz={26}
            style={{ letterSpacing: "-0.01em" }}
          >
            New Booking
          </Title>
          <Text size="sm" c="edr-muted" mt={4}>
            Fill in the details below to book your freight shipment.
          </Text>
        </Box>
        <Button
          variant="default"
          radius="md"
          leftSection={<ChevronLeft size={16} />}
          onClick={() => navigate("/bookings")}
        >
          Back to Bookings
        </Button>
      </Group>
      <form
        id="new-booking-form"
        className="flex flex-col"
        style={{ flex: 1 }}
        onSubmit={(e) => e.preventDefault()}
      >
        <Box flex={1} p="24px">
          <Box mb="lg">
            <StepIndicator step={step} steps={visibleSteps} />
          </Box>

          {persistAndPriceMutation.isError && (
            <Alert
              color="red"
              icon={<AlertCircle size={16} />}
              radius="md"
              mb="lg"
            >
              <Text size="sm" fw={600}>
                Failed to save booking or generate price
              </Text>
              <Text size="sm" mt={4} c="red.7">
                {persistAndPriceMutation.error instanceof Error
                  ? persistAndPriceMutation.error.message
                  : "An unexpected error occurred. Please try again."}
              </Text>
            </Alert>
          )}

          {step === 0 && (
            <Step0OperationType
              form={form}
              allowedOperations={allowedOperations}
              onSelect={handleOperationSelect}
            />
          )}
          {step === 1 && (
            <Step1ContractType form={form} referenceData={referenceData} />
          )}
          {step === 2 && (
            <Step2ServiceType referenceData={referenceData} form={form} />
          )}
          {step === 3 && (
            <Step5CargoDetails
              form={form}
              referenceData={referenceData}
              isLoading={refDataLoading}
            />
          )}
          {step === 4 && (
            <Step4Route
              form={form}
              referenceData={referenceData}
              isLoading={refDataLoading}
            />
          )}
          {step === 5 && (
            <StepScheduling form={form} referenceData={referenceData} />
          )}
          {step === 6 && <StepDocuments documents={onboardingDocs} />}
          {step === 7 && (
            <Step8Review
              form={form}
              setStep={setStep}
              direction={direction!}
              referenceData={referenceData}
              onboardingDocs={onboardingDocs}
              onSaveDraft={handleSaveDraft}
              onSubmit={handleSubmitBooking}
              saveDraftPending={
                persistAndPriceMutation.isPending &&
                persistAndPriceMutation.variables?.mode === "draft"
              }
              submitPending={
                persistAndPriceMutation.isPending &&
                persistAndPriceMutation.variables?.mode === "submit"
              }
            />
          )}
        </Box>

        {/* Navigation footer */}
        <Box
          style={{
            position: "sticky",
            bottom: 0,
            zIndex: 20,
            borderTop: "1px solid var(--mantine-color-edr-border-0)",
            backgroundColor: "rgba(255,255,255,0.94)",
            backdropFilter: "blur(14px)",
            WebkitBackdropFilter: "blur(14px)",
            padding: "16px 24px",
            marginTop: "auto",
          }}
        >
          <Group justify="space-between" className="mx-auto max-w-4xl">
            <Button
              type="button"
              variant="default"
              radius="md"
              leftSection={<ChevronLeft size={16} />}
              onClick={() => goToStep(-1)}
              disabled={isFirstStep}
            >
              Back
            </Button>

            {!isLastStep ? (
              <Button
                type="button"
                color="edr-green"
                radius="md"
                rightSection={<ChevronRight size={16} />}
                onClick={handleContinue}
              >
                Continue
              </Button>
            ) : (
              <Button
                type="button"
                color="edr-green"
                radius="md"
                leftSection={<Send size={16} />}
                onClick={handleSubmitBooking}
                loading={isPricing}
              >
                Submit
              </Button>
            )}
          </Group>
        </Box>
      </form>

      <Modal
        opened={priceModalMode !== null && pricingData !== null}
        onClose={closePriceModal}
        title={
          <Text fw={700}>
            {priceModalMode === "submit"
              ? "Confirm booking submission"
              : "Draft saved — price estimate"}
          </Text>
        }
        radius="lg"
        centered
        size="md"
      >
        {pricingData && (
          <Stack gap="md">
            <Text size="sm" c="dimmed">
              {priceModalMode === "submit"
                ? "Review your total price below. Confirm to submit for EDR staff review, or reject to discard this booking."
                : "Your booking has been saved as a draft. Here is your estimated total price."}
            </Text>
            <Box
              p="lg"
              style={{
                borderRadius: 16,
                border: "1px solid var(--mantine-color-edr-border-0)",
                background:
                  "linear-gradient(135deg, #F4FBF7 0%, #FFFFFF 70%)",
              }}
            >
              <Text size="xs" fw={700} tt="uppercase" c="edr-green" style={{ letterSpacing: "0.06em" }}>
                Total price
              </Text>
              <Text fw={800} fz={30} c="#10202F" mt={4}>
                {pricingData.totalAmount.toLocaleString()}{" "}
                <Text span fz={18} fw={700} c="edr-muted">
                  {pricingData.currency}
                </Text>
              </Text>
            </Box>
            {pricingData.warnings.length > 0 && (
              <Text size="xs" c="orange.7" p="xs" className="rounded bg-orange-50">
                {pricingData.warnings.join(", ")}
              </Text>
            )}
            <Group justify="flex-end" gap="sm" mt="md">
              {priceModalMode === "submit" ? (
                <>
                  <Button
                    variant="outline"
                    color="red"
                    radius="md"
                    leftSection={<XCircle size={16} />}
                    onClick={() => rejectMutation.mutate()}
                    loading={rejectMutation.isPending}
                    disabled={confirmMutation.isPending}
                  >
                    Reject
                  </Button>
                  <Button
                    color="edr-green"
                    radius="md"
                    leftSection={<Check size={16} />}
                    onClick={() => confirmMutation.mutate()}
                    loading={confirmMutation.isPending}
                    disabled={rejectMutation.isPending}
                  >
                    Confirm & submit
                  </Button>
                </>
              ) : (
                <Button color="edr-green" radius="md" onClick={handleDraftModalOk}>
                  OK
                </Button>
              )}
            </Group>
          </Stack>
        )}
      </Modal>

      <Modal
        opened={priceChangeResult !== null}
        onClose={() => setPriceChangeResult(null)}
        title={<Text fw={700}>Price has changed</Text>}
        radius="lg"
        centered
      >
        {priceChangeResult && (
          <Stack gap="md">
            <Text size="sm" c="dimmed">
              {priceChangeResult.message ??
                "The booking price has been updated. Confirm to submit with the new total."}
            </Text>
            {priceChangeResult.previousTotalAmount !== undefined && (
              <Group justify="space-between">
                <Text size="sm" c="dimmed">
                  Previous total
                </Text>
                <Text size="sm" td="line-through">
                  {priceChangeResult.previousTotalAmount.toLocaleString()}{" "}
                  {priceChangeResult.currency}
                </Text>
              </Group>
            )}
            <Group justify="space-between">
              <Text fw={700}>New total</Text>
              <Text fw={800} c="edr-green">
                {priceChangeResult.totalAmount.toLocaleString()}{" "}
                {priceChangeResult.currency}
              </Text>
            </Group>
            <Group justify="flex-end" gap="sm">
              <Button
                variant="default"
                radius="md"
                onClick={() => setPriceChangeResult(null)}
              >
                Cancel
              </Button>
              <Button
                color="edr-green"
                radius="md"
                loading={confirmSubmitMutation.isPending}
                onClick={() => confirmSubmitMutation.mutate()}
              >
                Confirm & submit
              </Button>
            </Group>
          </Stack>
        )}
      </Modal>

      <Modal
        opened={consolidationPending}
        onClose={() => {
          setConsolidationPending(false);
          if (priceBookingId) navigate(`/bookings/${priceBookingId}`);
        }}
        title={
          <Group gap={10} wrap="nowrap">
            <div
              className="flex shrink-0 items-center justify-center rounded-[11px] border border-[#F4D9A8]"
              style={{ width: 38, height: 38, backgroundColor: "#FDF3E0", color: "#C77F12" }}
            >
              <Link2 size={20} />
            </div>
            <Text fw={700}>Waiting to share a wagon</Text>
          </Group>
        }
        radius="lg"
        centered
        size="md"
      >
        <Stack gap="md">
          <Text size="sm" c="dimmed">
            Your booking is submitted, but your cargo only fills part of a wagon.
            We&apos;re pairing it with another shipment on the same route to share
            the space.
          </Text>
          <Box
            p="md"
            style={{
              borderRadius: 12,
              border: "1px solid #F4D9A8",
              background: "#FDF3E0",
            }}
          >
            <Text size="sm" fw={600} c="#10202F">
              What happens next
            </Text>
            <Text size="sm" mt={4} c="#7A6A4E">
              As soon as a matching shipment is found, your booking continues
              automatically — you&apos;ll be notified, and no action is needed
              from you until then. Your acceptance, approval and contract stay
              independent and yours alone.
            </Text>
          </Box>
          <Group justify="flex-end" gap="sm">
            <Button
              color="edr-green"
              radius="md"
              onClick={() => {
                setConsolidationPending(false);
                if (priceBookingId) navigate(`/bookings/${priceBookingId}`);
              }}
            >
              Got it
            </Button>
          </Group>
        </Stack>
      </Modal>

      <Modal
        opened={cancelDialogOpen}
        onClose={() => setCancelDialogOpen(false)}
        title={<Text fw={700}>Abort booking</Text>}
        radius="lg"
        centered
      >
        <Stack gap="md">
          <Text size="sm" c="dimmed">
            Are you sure you want to abort this booking? This action cannot be
            undone.
          </Text>
          <TextInput
            label="Reason for cancellation (optional)"
            placeholder="e.g. Change of plans…"
            value={cancelReason}
            onChange={(e) => setCancelReason(e.currentTarget.value)}
            radius="md"
            data-autofocus
          />
          <Group justify="flex-end" gap="sm">
            <Button
              variant="default"
              radius="md"
              onClick={() => setCancelDialogOpen(false)}
            >
              Keep editing
            </Button>
            <Button
              color="red"
              radius="md"
              onClick={() =>
                abortMutation.mutate(
                  cancelReason.trim() || "Aborted by customer",
                )
              }
              disabled={abortMutation.isPending}
              loading={abortMutation.isPending}
              leftSection={
                !abortMutation.isPending ? <XCircle size={15} /> : undefined
              }
            >
              Yes, abort
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Box>
  );
}
