import { useEffect, useMemo } from "react";
import { Controller, useFieldArray, type UseFormReturn } from "react-hook-form";
import { Package, Plus, Trash2, Weight } from "lucide-react";
import { ActionIcon, Button, Skeleton, Text, TextInput } from "@mantine/core";
import type { Freight } from "@edr/types";
import {
  BookingFormInputValues,
  calcWagons,
  type BookingFormValues,
} from "./schema";
import {
  AlertBox,
  fieldStyles,
  OptionCard,
  OptionFieldError,
  SelectField,
  StepCard,
  StepHeader,
  StepLabel,
} from "./shared";

type BookingForm = UseFormReturn<
  BookingFormInputValues,
  any,
  BookingFormValues
>;

export function Step5CargoDetails({
  form,
  referenceData,
  isLoading,
}: {
  form: BookingForm;
  referenceData?: Freight.BookingReferenceData;
  isLoading?: boolean;
}) {
  const cargoType = form.watch("cargoType");
  const cargoTypePath = form.watch("cargoTypePath") ?? [];
  const parentId = cargoTypePath[0];
  const childId = cargoTypePath[1];
  const containers = form.watch("containers");
  // General contracts reserve quantity per route, captured in the route step
  // against each route. So the single cargo-level quantity below is only asked
  // for one-time bookings; contracts skip it here to avoid a duplicate input.
  const isGeneralContract = form.watch("bookingType") === "general_contract";

  const { fields, append, remove } = useFieldArray({
    control: form.control,
    name: "containers",
  });

  const containerTypeOptionsBySize = useMemo(() => {
    if (!referenceData?.containers) return new Map<string, string[]>();
    return new Map(
      referenceData.containers.map((g) => [g.size, g.types.map((t) => t.name)]),
    );
  }, [referenceData]);

  useEffect(() => {
    if (parentId) {
      form.setValue("cargoTypePath", [parentId, ""], { shouldDirty: true });
    }
  }, [parentId]);

  const selectedCommodity = useMemo(() => {
    if (!referenceData?.cargo_type || !parentId || !childId) return null;
    const group = referenceData.cargo_type.find((g) => g.id === parentId);
    return group?.children?.find((c) => c.id === childId) ?? null;
  }, [referenceData, parentId, childId]);

  // Unit of measure for bulk/break-bulk cargo: PER_ITEM → ask for a total item
  // count; otherwise ask for an estimated tonnage. Drives the quantity field's
  // label, icon, and step so customers enter the right unit.
  const isPerItem = selectedCommodity?.unit_of_measure === "PER_ITEM";

  const freightTypeGroups = useMemo(() => {
    if (!referenceData?.cargo_type) return [];
    return referenceData.cargo_type.filter(
      (g) => g.code !== "CONTAINER" && !/container/i.test(g.name),
    );
  }, [referenceData]);

  const freightTypeOptions = useMemo(
    () =>
      freightTypeGroups.map((g) => ({
        value: g.id,
        label: g.name,
      })),
    [freightTypeGroups],
  );

  const commodityOptions = useMemo(() => {
    if (!referenceData?.cargo_type || !parentId) return [];
    const group = referenceData.cargo_type.find((g) => g.id === parentId);
    return (
      group?.children?.map((c) => ({
        value: c.id,
        label: c.name,
      })) ?? []
    );
  }, [referenceData, parentId]);

  if (isLoading) {
    return (
      <StepCard>
        <StepHeader
          icon={<Package size={22} />}
          title="Cargo Details"
          description="Choose your cargo type and configuration."
        />
        <div className="space-y-4">
          <Skeleton height={14} w={96} radius="sm" />
          <div className="grid gap-4 sm:grid-cols-2">
            <Skeleton height={96} radius="lg" />
            <Skeleton height={96} radius="lg" />
          </div>
          <Skeleton height={44} radius="md" />
          <Skeleton height={44} w="33%" radius="md" />
        </div>
      </StepCard>
    );
  }

  return (
    <StepCard>
      <StepHeader
        icon={<Package size={22} />}
        title="Cargo Details"
        description="Choose your cargo type and configuration. Container weight is captured later in operations."
      />

      {/* Cargo Type */}
      <div className="space-y-3">
        <StepLabel>Cargo Type *</StepLabel>
        <Controller
          name="cargoType"
          control={form.control}
          render={({ field, fieldState }) => (
            <div>
              <div className="grid gap-4 sm:grid-cols-2">
                <OptionCard
                  selected={cargoType === "container"}
                  icon={<Package className="h-5 w-5" />}
                  iconBg="#ECF6F1"
                  iconColor="#0A6F4D"
                  title="Containerized"
                  description="Pre-packed containerized cargo (20ft / 40ft)."
                  onClick={() => {
                    field.onChange("container");
                    form.setValue("cargoTypePath", [], { shouldDirty: true });
                  }}
                />
                <OptionCard
                  selected={cargoType === "bulk"}
                  icon={<Weight className="h-5 w-5" />}
                  iconBg="#FDF3E0"
                  iconColor="#C77F09"
                  title="General Cargo"
                  description="Bulk commodities or break-bulk cargo."
                  onClick={() => {
                    field.onChange("bulk");
                    form.setValue("containers", [], { shouldDirty: true });
                  }}
                />
              </div>
              <OptionFieldError error={fieldState.error} />
            </div>
          )}
        />
      </div>

      {/* Bulk freight type — pick the commodity FIRST so we know whether the
          cargo is measured in tons or items before asking for the quantity. */}
      {cargoType === "bulk" && (
        <div className="space-y-3">
          {freightTypeOptions.length > 0 ? (
            <Controller
              name="cargoTypePath.0"
              control={form.control}
              render={({ field, fieldState }) => (
                <SelectField
                  field={field}
                  error={fieldState.error}
                  label="Bulk Cargo Type *"
                  placeholder="Select freight type..."
                  data={freightTypeOptions}
                />
              )}
            />
          ) : (
            <Text size="sm" c="dimmed">
              No freight types available.
            </Text>
          )}

          {parentId && commodityOptions.length > 0 && (
            <Controller
              name="cargoTypePath.1"
              control={form.control}
              render={({ field, fieldState }) => (
                <SelectField
                  field={field}
                  error={fieldState.error}
                  label="Commodity *"
                  placeholder="Select type..."
                  data={commodityOptions}
                />
              )}
            />
          )}

          {selectedCommodity?.show_free_text_box && (
            <Controller
              name="cargoFreeText"
              control={form.control}
              render={({ field, fieldState }) => (
                <TextInput
                  {...field}
                  label="Describe cargo *"
                  placeholder="e.g. Charcoal, Wheat, etc."
                  error={fieldState.error?.message}
                  radius="md"
                />
              )}
            />
          )}

          {/* Quantity — only once a commodity is chosen, so the unit (tons vs
              items) is known. PER_TON asks for estimated tons; PER_ITEM asks
              for the total item count. General contracts collect this per route
              in the route step instead, so it's hidden here for them. */}
          {selectedCommodity && !isGeneralContract && (
            <Controller
              name="cargoWeight"
              control={form.control}
              render={({ field, fieldState }) => (
                <TextInput
                  {...field}
                  id="cargoWeight"
                  type="number"
                  label={isPerItem ? "Quantity (Items) *" : "Quantity (Tons) *"}
                  placeholder={isPerItem ? "e.g. 500" : "e.g. 1200"}
                  leftSection={
                    isPerItem ? (
                      <Package className="h-4 w-4" />
                    ) : (
                      <Weight className="h-4 w-4" />
                    )
                  }
                  error={fieldState.error?.message}
                  description={
                    isPerItem
                      ? "Total count of items you plan to import or export."
                      : "Estimated total tonnage to ship."
                  }
                  radius={10}
                  styles={fieldStyles}
                  min={0}
                  step={isPerItem ? 1 : 0.01}
                />
              )}
            />
          )}
        </div>
      )}

      {/* Container list — type + quantity only; no weight is collected here. */}
      {cargoType === "container" && (
        <>
          <div className="space-y-4">
            <div className="flex items-center justify-between">
              <StepLabel>Containers</StepLabel>
              <Button
                type="button"
                variant="default"
                size="sm"
                radius="md"
                leftSection={<Plus size={14} />}
                onClick={() =>
                  append({
                    type: "20ft",
                    containerType: "",
                    qty: "1",
                    vgm: "0",
                  })
                }
              >
                Add Container
              </Button>
            </div>

            {fields.map((field, index) => (
              <div
                key={field.id}
                className="flex flex-col gap-3 rounded-xl border border-gray-200 bg-gray-50/50 p-4"
              >
                <div className="flex items-center justify-between">
                  <Text
                    size="xs"
                    fw={600}
                    c="dimmed"
                    tt="uppercase"
                    className="tracking-wide"
                  >
                    Container {index + 1}
                  </Text>
                  {fields.length > 1 && (
                    <ActionIcon
                      color="red"
                      variant="subtle"
                      size="sm"
                      onClick={() => remove(index)}
                      aria-label="Remove container"
                    >
                      <Trash2 size={15} />
                    </ActionIcon>
                  )}
                </div>

                {/* Container size */}
                <Controller
                  name={`containers.${index}.type`}
                  control={form.control}
                  render={({ field: typeField, fieldState }) => (
                    <div>
                      <div className="grid gap-2 sm:grid-cols-2">
                        {[
                          { val: "20ft" as const, label: "20ft Container (TEU)" },
                          { val: "40ft" as const, label: "40ft Container (FEU)" },
                        ].map((ct) => (
                          <OptionCard
                            key={ct.val}
                            selected={typeField.value === ct.val}
                            onClick={() => typeField.onChange(ct.val)}
                          >
                            <div className="flex items-center gap-2">
                              <Package className="h-4 w-4 text-emerald-600" />
                              <p className="font-semibold">{ct.label}</p>
                            </div>
                          </OptionCard>
                        ))}
                      </div>
                      <OptionFieldError error={fieldState.error} />
                    </div>
                  )}
                />

                {/* Quantity + Container Type */}
                <div className="grid gap-3 sm:grid-cols-2">
                  <Controller
                    name={`containers.${index}.qty`}
                    control={form.control}
                    render={({ field: qtyField, fieldState }) => (
                      <div>
                        <Text size="sm" fw={500} mb={4}>
                          Quantity *
                        </Text>
                        <div className="flex items-center gap-2">
                          <button
                            type="button"
                            onClick={() =>
                              qtyField.onChange(
                                Math.max(
                                  1,
                                  Number(qtyField.value ?? 1) - 1,
                                ).toString(),
                              )
                            }
                            className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-gray-200 bg-white text-sm font-medium transition hover:bg-gray-50"
                          >
                            −
                          </button>
                          <input
                            value={qtyField.value ?? 1}
                            onChange={(e) => qtyField.onChange(e.target.value)}
                            onBlur={qtyField.onBlur}
                            type="number"
                            min={1}
                            className="h-9 w-full rounded-lg border border-gray-200 bg-white px-3 text-center text-sm outline-none focus:border-emerald-500 focus:ring-1 focus:ring-emerald-500"
                          />
                          <button
                            type="button"
                            onClick={() =>
                              qtyField.onChange(
                                (Number(qtyField.value ?? 1) + 1).toString(),
                              )
                            }
                            className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-gray-200 bg-white text-sm font-medium transition hover:bg-gray-50"
                          >
                            +
                          </button>
                        </div>
                        {fieldState.error?.message && (
                          <Text size="xs" c="red" mt={4}>
                            {fieldState.error.message}
                          </Text>
                        )}
                      </div>
                    )}
                  />

                  <Controller
                    name={`containers.${index}.containerType`}
                    control={form.control}
                    render={({ field: ctField, fieldState }) => (
                      <SelectField
                        field={ctField}
                        error={fieldState.error}
                        label="Container Type *"
                        placeholder="Select type..."
                        data={
                          containerTypeOptionsBySize.get(
                            containers[index]?.type ?? "20ft",
                          ) ?? []
                        }
                      />
                    )}
                  />
                </div>
              </div>
            ))}
          </div>

          {(() => {
            const result = calcWagons(containers ?? []);
            if (result.hasOddUnit) {
              return (
                <AlertBox tone="warning">
                  <p className="font-semibold">Unpaired 20ft Container</p>
                  <p className="mt-1 text-xs">
                    One 20ft container occupies only half a wagon. The wagon will
                    depart once a co-loader is found to fill the remaining slot,
                    which <strong>may delay departure</strong> beyond the standard
                    lead time.
                  </p>
                </AlertBox>
              );
            }
            return null;
          })()}
        </>
      )}
    </StepCard>
  );
}
