import { useMemo } from "react";
import { Controller, useFieldArray, type UseFormReturn } from "react-hook-form";
import { MapPin, Package, Plus, Trash2, Weight } from "lucide-react";
import {
  Button,
  Field,
  FieldError,
  FieldLabel,
  Input,
  Skeleton,
} from "@edr/ui-common";
import type { Freight } from "@edr/types";
import {
  BookingFormInputValues,
  calcWagons,
  type BookingFormValues,
  type RouteDirection,
} from "./schema";
import {
  AlertBox,
  OptionCard,
  SelectField,
  SelectItem,
  StepHeader,
  StepLabel,
} from "./shared";

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

export function Step5CargoDetails({
  form,
  direction,
  referenceData,
  isLoading,
}: {
  form: BookingForm;
  direction: RouteDirection;
  referenceData?: Freight.BookingReferenceData;
  isLoading?: boolean;
}) {
  const cargoType = form.watch("cargoType");
  const freightType = form.watch("freightType");
  const bulkCommoditytype = form.watch("bulkCommoditytype");
  const containers = form.watch("containers");

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

  const containerTypeOptions = useMemo(() => {
    if (!referenceData?.containers) return [];
    return referenceData.containers.flatMap((group) =>
      group.types.map((t) => t.name),
    );
  }, [referenceData]);

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

  const commodityOptions = useMemo(() => {
    if (!referenceData?.cargo_type || !freightType) return [];
    const group = referenceData.cargo_type.find(
      (g) => g.code.toLowerCase() === freightType,
    );
    return group?.children?.map((c) => c.name) ?? [];
  }, [referenceData, freightType]);

  function getOverweightAlert(
    type: "20ft" | "40ft",
    vgm: number,
  ): string | null {
    if (type === "20ft" && vgm > 0) {
      const limit = direction === "export" ? 25 : 20;
      if (vgm > limit) {
        return `VGM ${vgm}t exceeds the ${limit}t ${direction ?? "standard"} limit for a 20ft container. An Overweight Surcharge will apply.`;
      }
    }
    if (type === "40ft" && vgm > 32.5) {
      return `VGM ${vgm}t exceeds the 32.5t global limit for a 40ft container. An Overweight Surcharge will apply.`;
    }
    return null;
  }

  if (isLoading) {
    return (
      <div className="space-y-6">
        <StepHeader
          title="Cargo Details"
          description="Define your cargo type, weight, and container configuration."
        />
        <div className="space-y-4 rounded-xl border border-border p-4">
          <Skeleton className="h-4 w-24" />
          <div className="grid gap-3 sm:grid-cols-2">
            <Skeleton className="h-24 w-full" />
            <Skeleton className="h-24 w-full" />
          </div>
          <Skeleton className="h-10 w-full" />
          <Skeleton className="h-10 w-1/3" />
        </div>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <StepHeader
        title="Cargo Details"
        description="Define your cargo type, weight, and container configuration."
      />

      <div className="space-y-3">
        <StepLabel>Cargo Type *</StepLabel>
        <Controller
          name="cargoType"
          control={form.control}
          render={({ field, fieldState }) => (
            <Field data-invalid={fieldState.invalid}>
              <div className="grid gap-3 sm:grid-cols-2">
                <OptionCard
                  selected={cargoType === "container"}
                  onClick={() => {
                    field.onChange("container");
                    form.setValue("freightType", "", {
                      shouldDirty: true,
                    });
                  }}
                >
                  <div className="mb-2 flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10">
                    <Package className="h-4 w-4 text-primary" />
                  </div>
                  <p className="font-semibold">Containerized</p>
                  <p className="mt-0.5 text-xs text-muted-foreground">
                    Pre-packed containerized cargo (20ft / 40ft).
                  </p>
                </OptionCard>
                <OptionCard
                  selected={cargoType === "bulk"}
                  onClick={() => {
                    field.onChange("bulk");
                    form.setValue("containers", [], { shouldDirty: true });
                  }}
                >
                  <div className="mb-2 flex h-9 w-9 items-center justify-center rounded-lg bg-amber-100">
                    <Weight className="h-4 w-4 text-amber-600" />
                  </div>
                  <p className="font-semibold">General Cargo</p>
                  <p className="mt-0.5 text-xs text-muted-foreground">
                    Bulk commodities or break-bulk cargo.
                  </p>
                </OptionCard>
              </div>
              <FieldError errors={[fieldState.error]} />
            </Field>
          )}
        />
      </div>

      <div className="space-y-3">
        <StepLabel>Weight</StepLabel>
        <Controller
          name="cargoWeight"
          control={form.control}
          render={({ field, fieldState }) => (
            <Field data-invalid={fieldState.invalid}>
              <FieldLabel htmlFor="cargoWeight">
                Total Cargo Weight(Tons)*
              </FieldLabel>
              <div className="relative">
                <Weight className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                <Input
                  {...field}
                  id="cargoWeight"
                  type="number"
                  aria-invalid={fieldState.invalid}
                  placeholder="0.00"
                  className="pl-9"
                  min="0"
                  step="0.01"
                />
              </div>
              <FieldError errors={[fieldState.error]} />
            </Field>
          )}
        />
      </div>
      {cargoType === "bulk" && (
        <div className="space-y-3">
          <StepLabel>Freight Type *</StepLabel>
          <Controller
            name="freightType"
            control={form.control}
            render={({ field, fieldState }) => (
              <Field data-invalid={fieldState.invalid}>
                <div className="grid gap-3 sm:grid-cols-2">
                  {freightTypeGroups.map((group) => {
                    const val = group.code.toLowerCase();
                    return (
                      <OptionCard
                        key={group.code}
                        selected={freightType === val}
                        onClick={() => {
                          field.onChange(val);
                          form.setValue("bulkCommoditytype", "", {
                            shouldDirty: true,
                          });
                        }}
                      >
                        <p className="font-semibold">{group.name}</p>
                      </OptionCard>
                    );
                  })}
                </div>
                <FieldError errors={[fieldState.error]} />
              </Field>
            )}
          />

          {freightType && commodityOptions.length > 0 && (
            <div className="space-y-2">
              <Controller
                name="bulkCommoditytype"
                control={form.control}
                render={({ field, fieldState }) => (
                  <SelectField
                    field={field}
                    error={fieldState.error}
                    label="Cargo type *"
                    placeholder="Select type *"
                  >
                    {commodityOptions.map((option) => (
                      <SelectItem key={option} value={option}>
                        {option}
                      </SelectItem>
                    ))}
                  </SelectField>
                )}
              />
            </div>
          )}
        </div>
      )}

      {cargoType === "container" && (
        <>
          <div className="space-y-4">
            <div className="flex items-center justify-between">
              <StepLabel>Containers</StepLabel>
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={() =>
                  append({
                    type: "20ft",
                    containerType: "",
                    qty: "1",
                    vgm: "",
                  })
                }
              >
                <Plus className="mr-1 h-3.5 w-3.5" />
                Add Container
              </Button>
            </div>

            {fields.map((field, index) => {
              const containerType = containers[index]?.type;
              const vgm = containers[index]?.vgm ?? 0;
              const alert = getOverweightAlert(containerType, +vgm);

              return (
                <div
                  key={field.id}
                  className="rounded-xl flex flex-col border border-border p-3 gap-2"
                >
                  <div className="flex items-center justify-between">
                    {fields.length > 1 && (
                      <button
                        type="button"
                        onClick={() => remove(index)}
                        className="text-xs text-destructive hover:underline"
                      >
                        <Trash2 className="h-3.5 w-3.5" />
                      </button>
                    )}
                  </div>

                  <Controller
                    name={`containers.${index}.type`}
                    control={form.control}
                    render={({ field: typeField, fieldState }) => (
                      <Field data-invalid={fieldState.invalid}>
                        <div className="grid gap-2 sm:grid-cols-2">
                          {[
                            {
                              val: "20ft" as const,
                              label: "20ft Container (TEU)",
                              limit:
                                direction === "export"
                                  ? "Max 25t per container"
                                  : "Max 20t per container",
                            },
                            {
                              val: "40ft" as const,
                              label: "40ft Container (FEU)",
                              limit: "Max 32.5t per container",
                            },
                          ].map((ct) => (
                            <OptionCard
                              key={ct.val}
                              selected={typeField.value === ct.val}
                              onClick={() => typeField.onChange(ct.val)}
                            >
                              <div className="mb-1 flex items-center gap-2">
                                <Package className="h-4 w-4 text-primary" />
                                <p className="font-semibold">{ct.label}</p>
                              </div>
                              <p className="text-xs text-muted-foreground">
                                {ct.limit}
                              </p>
                            </OptionCard>
                          ))}
                        </div>
                        <FieldError errors={[fieldState.error]} />
                      </Field>
                    )}
                  />

                  <div className="grid gap-3 sm:grid-cols-3">
                    <Controller
                      name={`containers.${index}.qty`}
                      control={form.control}
                      render={({ field: qtyField, fieldState }) => (
                        <Field data-invalid={fieldState.invalid}>
                          <FieldLabel>Quantity *</FieldLabel>
                          <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-input transition hover:bg-accent"
                            >
                              -
                            </button>
                            <Input
                              value={qtyField.value ?? 1}
                              onChange={(e) =>
                                qtyField.onChange(e.target.value)
                              }
                              onBlur={qtyField.onBlur}
                              type="number"
                              aria-invalid={fieldState.invalid}
                              className="text-center"
                              min="1"
                            />
                            <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-input transition hover:bg-accent"
                            >
                              +
                            </button>
                          </div>
                          <FieldError errors={[fieldState.error]} />
                        </Field>
                      )}
                    />

                    <Controller
                      name={`containers.${index}.vgm`}
                      control={form.control}
                      render={({ field: vgmField, fieldState }) => (
                        <Field data-invalid={fieldState.invalid}>
                          <FieldLabel>Tons*</FieldLabel>
                          <Input
                            value={vgmField.value ?? 0}
                            onChange={(e) => vgmField.onChange(e.target.value)}
                            onBlur={vgmField.onBlur}
                            type="number"
                            aria-invalid={fieldState.invalid}
                            placeholder="e.g. 18.5"
                            min="0"
                            step="0.1"
                          />
                          <FieldError errors={[fieldState.error]} />
                        </Field>
                      )}
                    />

                    <Controller
                      name={`containers.${index}.containerType`}
                      control={form.control}
                      render={({ field: ctField, fieldState }) => (
                        <SelectField
                          field={ctField}
                          error={fieldState.error}
                          label="Container Type *"
                          placeholder="Select type..."
                        >
                          {containerTypeOptions.map((option) => (
                            <SelectItem key={option} value={option}>
                              {option}
                            </SelectItem>
                          ))}
                        </SelectField>
                      )}
                    />
                  </div>

                  {alert && (
                    <AlertBox tone="warning">
                      <strong>Overweight Alert:</strong> {alert}
                    </AlertBox>
                  )}
                </div>
              );
            })}
          </div>

          {(() => {
            const result = calcWagons(containers ?? []);
            if (result.hasOddUnit) {
              return (
                <AlertBox tone="warning">
                  <div className="flex items-start gap-2">
                    <div>
                      <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>
                    </div>
                  </div>
                </AlertBox>
              );
            }
            return null;
          })()}
        </>
      )}
    </div>
  );
}
