import { useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import {
  AlertCircle,
  Check,
  ChevronLeft,
  ChevronRight,
  LoaderCircle,
} from "lucide-react";
import { Button } from "@edr/ui-common";
import { api } from "@/services/api";
import type { CreateBookingPayload } from "@/services/bookings.service";
import {
  BookingFormInputValues,
  STEPS,
  bookingFormSchema,
  getRouteDirection,
  initialBookingFormValues,
  stepFields,
  type BookingFormValues,
} from "./new-booking-form/schema";
import { StepIndicator } from "./new-booking-form/StepIndicator";
import {
  Step1ContractType,
  Step2ServiceType,
  Step4Route,
  Step5CargoDetails,
  Step8Review,
} from "./new-booking-form/steps";

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

  const createMutation = useMutation({
    mutationFn: (payload: CreateBookingPayload) =>
      api.bookings.create.call(payload),
    onSuccess: (booking) => {
      queryClient.invalidateQueries({ queryKey: api.bookings.list.queryKey() });
      navigate(`/bookings/${booking.id}`);
    },
  });

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

  const originYard = form.watch("originYard");
  const destinationYard = form.watch("destinationYard");

  const direction = useMemo(
    () => getRouteDirection(originYard, destinationYard),
    [originYard, destinationYard],
  );

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

    setStep((currentStep) => Math.min(STEPS.length, currentStep + 1));
  }

  const handleSubmit = form.handleSubmit((data) => {
    if (data.contractType === "renewal" && !data.previousContractRef) {
      form.setError("previousContractRef", {
        type: "manual",
        message: "Select a previous contract reference.",
      });
      setStep(1);
      return;
    }

    const totalWeight =
      data.cargoType === "container"
        ? data.containers.reduce(
          (acc, c) => acc + Number(c.vgm || 0) * Number(c.qty || 0),
          0,
        )
        : Number(data.cargoWeight || 0);

    // ── Reference data lookups ──────────────────────────────────────────
    const yards = referenceData?.yard ?? [];
    const services = referenceData?.service ?? [];
    const shippingLines = referenceData?.shipping_line ?? [];
    const cargoTree = referenceData?.cargo_type ?? [];
    const containerGroups = referenceData?.containers ?? [];

    const findYardId = (name: string): string =>
      yards.find((y) => y.name === name)?.id ?? "";

    const findServiceTypeId = (): string => {
      const code = data.serviceType === "rail" ? "RAIL" : "RAIL_AND_FORWARDING";
      return services.find((s) => s.code === code)?.id ?? services[0]?.id ?? "";
    };

    const findShippingLineId = (name: string): string | undefined =>
      shippingLines.find((l) => l.name === name)?.id;

    const findCargoTypeId = (name: string): string | undefined => {
      for (const group of cargoTree) {
        const child = group.children?.find((c) => c.name === name);
        if (child) return child.id;
      }
      return undefined;
    };

    const findContainerCargoTypeId = (): string => {
      const group = cargoTree.find(
        (g) => g.code === "CONTAINER" || /container/i.test(g.name),
      );
      return group?.id ?? "";
    };

    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 selectedChild =
      data.cargoType !== "container" && data.bulkCommoditytype
        ? cargoTree
          .find((g) => g.code.toLowerCase() === data.freightType)
          ?.children?.find((c) => c.name === data.bulkCommoditytype)
        : undefined;

    const cargoTypeId =
      data.cargoType === "container"
        ? findContainerCargoTypeId()
        : selectedChild?.id ?? "";

    const cargoFreeText =
      data.cargoType === "container"
        ? undefined
        : selectedChild?.show_free_text_box
          ? data.bulkCommoditytype
          : undefined;

    // ── Build API payload ───────────────────────────────────────────────
    const apiPayload: CreateBookingPayload = {
      scheduledDate: new Date().toISOString().slice(0, 10),
      contractType:
        data.contractType.toUpperCase() as CreateBookingPayload["contractType"],
      serviceTypeId: findServiceTypeId(),
      equipmentReturn:
        data.equipmentReturn === "with_return"
          ? "WITH_RETURN"
          : "WITHOUT_RETURN",
      originYardId: findYardId(data.originYard),
      destinationYardId: findYardId(data.destinationYard),
      tradeDirection:
        direction === "export"
          ? "EXPORT"
          : direction === "domestic"
            ? "DOMESTIC"
            : "IMPORT",
      cargoTypeId: data.cargoType === "container" ? undefined : cargoTypeId,
      cargoTotalWeightVgm: totalWeight,
      isHazardous: data.isHazardous,
      paymentCurrency: "USD",
      allowConsolidation: data.consolidationEnabled,
      // @ts-ignore
      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),
            vgmPerUnitTons: Number(c.vgm || 0),
          }))
          : [],
      ...(data.previousContractRef
        ? { previousContractId: data.previousContractRef }
        : {}),
      ...(data.contractType === "renewal" && data.previousContractRef
        ? { pnrCode: data.previousContractRef }
        : {}),
      ...(data.serviceType === "rail_forwarding" && data.firstMile.enabled
        ? { firstMilePickupAddress: data.firstMile.pickUpAddress }
        : {}),
      ...(data.serviceType === "rail_forwarding" && data.lastMile.enabled
        ? { lastMileDeliveryAddress: data.lastMile.deliveryAddress }
        : {}),
      ...(data.shippingLine
        ? { shippingLineId: findShippingLineId(data.shippingLine) }
        : {}),
      ...(cargoFreeText ? { cargoFreeText } : {}),
    };

    createMutation.mutate(apiPayload);
  });

  return (
    <form
      id="new-booking-form"
      className="flex flex-col"
      onSubmit={handleSubmit}
    >
      <div className="sticky top-0 z-20">
        <div className="mx-auto max-w-4xl space-y-3 px-6 pt-4">
          <StepIndicator step={step} />
        </div>
      </div>

      <div className="flex-1">
        <div className="mx-auto max-w-4xl px-6 py-8">
          {createMutation.isError && (
            <div className="mb-6 flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 p-4 text-sm text-red-800">
              <AlertCircle className="mt-0.5 h-4 w-4 shrink-0 text-red-500" />
              <div>
                <p className="font-semibold">Failed to save draft</p>
                <p className="mt-1 text-red-600">
                  {createMutation.error instanceof Error
                    ? createMutation.error.message
                    : "An unexpected error occurred. Please try again."}
                </p>
              </div>
            </div>
          )}
          {step === 1 && <Step1ContractType form={form} />}
          {step === 2 && <Step2ServiceType form={form} />}
          {step === 3 && (
            <Step4Route
              form={form}
              referenceData={referenceData}
              isLoading={refDataLoading}
            />
          )}
          {step === 4 && (
            <Step5CargoDetails
              form={form}
              direction={direction}
              referenceData={referenceData}
              isLoading={refDataLoading}
            />
          )}
          {step === 5 && (
            <Step8Review form={form} setStep={setStep} direction={direction} />
          )}
        </div>
      </div>

      <div className="sticky bottom-0 z-20 border-t border-border bg-background px-6 py-4">
        <div className="mx-auto flex max-w-4xl items-center justify-between">
          <Button
            type="button"
            variant="outline"
            onClick={() =>
              setStep((currentStep) => Math.max(1, currentStep - 1))
            }
            disabled={step === 1}
          >
            <ChevronLeft className="mr-1 h-4 w-4" />
            Back
          </Button>
          {step < STEPS.length ? (
            <Button type="button" onClick={handleContinue}>
              Continue
              <ChevronRight />
            </Button>
          ) : (
            <Button
              type="submit"
              form="new-booking-form"
              disabled={createMutation.isPending}
            >
              {createMutation.isPending ? (
                <LoaderCircle className="h-4 w-4 animate-spin" />
              ) : (
                <Check />
              )}
              {createMutation.isPending ? "Saving Draft..." : "Save as Draft"}
            </Button>
          )}
        </div>
      </div>
    </form>
  );
}
