import { useEffect, useMemo, useRef, useState } from "react";
import { Controller, type UseFormReturn } from "react-hook-form";
// Snowflake — restore with the Refrigerated Cargo switch below.
import { Container, Flame, RotateCcw } from "lucide-react";
import {
  Badge,
  Box,
  Button,
  Group,
  Loader,
  Modal,
  Select,
  Skeleton,
  Stack,
  Switch,
  Text,
  TextInput,
} from "@mantine/core";
import { useQuery } from "@tanstack/react-query";
import { SmartFileInput } from "@edr/ui-common";
import { HAZARD_CLASSES, hazardClassLabel, type Freight } from "@edr/types";
import { api } from "@/services/api";
import {
  CONTAINER_SIZES,
  ContractFormInputValues,
  type ContractDocuments,
  type ContractFormValues,
} from "./schema";
import { operationToTradeDirection } from "./helpers";
import { AlertBox, fieldStyles, SelectField, StepLabel } from "./shared";

/**
 * file_upload_settings code holding the hazardous-cargo document requirements.
 * Fields are configured by an admin in the backoffice file-settings editor —
 * whatever is configured there is what the modal asks for.
 */
const HAZARDOUS_DOC_SETTING_CODE = "hazardous_documents";

function hasUploaded(value: File | File[] | null | undefined): boolean {
  if (!value) return false;
  return Array.isArray(value) ? value.length > 0 : true;
}

const CARGO_TYPE_OPTIONS = [
  { value: "container", label: "Containerized (20ft / 40ft)" },
  { value: "bulk", label: "General / Bulk cargo" },
];

type ContractForm = UseFormReturn<
  ContractFormInputValues,
  any,
  ContractFormValues
>;

/**
 * Contract cargo SCOPE step (doc §7 step 3). Defines WHAT cargo the contract
 * covers — never HOW MUCH:
 *   - container: enabled sizes (20ft / 40ft) + optional commodity label
 *   - bulk: a single cargo-type commodity
 *   - shared hazardous / refrigerated billing flags
 * No quantity, VGM, or container-type detail is collected (that is captured at
 * booking time).
 */
export function Step3CargoScope({
  form,
  referenceData,
  isLoading,
}: {
  form: ContractForm;
  referenceData?: Freight.BookingReferenceData;
  isLoading?: boolean;
}) {
  const cargoType = form.watch("cargoType");
  const cargoTypePath = form.watch("cargoTypePath") ?? [];
  const parentId = cargoTypePath[0];

  // Hazardous cargo is a ONE-TIME-contract-only option; refrigerated cargo and
  // empty-container return are offered on IMPORT operations only.
  const operationType = form.watch("operationType");
  const isOneTime = (form.watch("contractKind") ?? "one_time") === "one_time";
  const isImport = operationType
    ? operationToTradeDirection(operationType) === "IMPORT"
    : false;

  const hazardSettingQuery = useQuery(
    api.fileUploadSettings.getByCode.queryOptions({
      input: { code: HAZARDOUS_DOC_SETTING_CODE },
      enabled: isOneTime,
    }),
  );
  const hazardFields = hazardSettingQuery.data?.fields ?? [];
  const hazardKeys = useMemo(
    () => hazardFields.map((f) => f.fileKey),
    [hazardFields],
  );

  const [hazardModalOpen, setHazardModalOpen] = useState(false);
  const [hazardDraft, setHazardDraft] = useState<ContractDocuments>({});
  const [hazardErrors, setHazardErrors] = useState<Record<string, string>>({});
  // Dangerous-goods declaration, edited in the modal and only written back to
  // the form once the customer confirms — cancelling must leave the contract
  // exactly as it was.
  const [classDraft, setClassDraft] = useState<string | null>(null);
  const [unDraft, setUnDraft] = useState("");
  const [declErrors, setDeclErrors] = useState<{
    hazardClass?: string;
    unNumber?: string;
  }>({});

  const hazardClass = form.watch("hazardClass");
  const unNumber = form.watch("unNumber");

  /** Drop every hazardous document from the contract's document map. */
  const clearHazardDocs = () => {
    const docs = { ...((form.getValues("documents") ?? {}) as ContractDocuments) };
    let changed = false;
    for (const key of hazardKeys) {
      if (key in docs) {
        delete docs[key];
        changed = true;
      }
    }
    if (changed) form.setValue("documents", docs, { shouldDirty: true });
  };

  const openHazardModal = () => {
    const docs = (form.getValues("documents") ?? {}) as ContractDocuments;
    setHazardDraft(
      Object.fromEntries(
        hazardKeys.filter((k) => k in docs).map((k) => [k, docs[k]]),
      ),
    );
    setHazardErrors({});
    setClassDraft(form.getValues("hazardClass") || null);
    setUnDraft(form.getValues("unNumber") ?? "");
    setDeclErrors({});
    setHazardModalOpen(true);
  };

  const confirmHazardDocs = () => {
    const missing = hazardFields.filter(
      (f) => f.isRequired && !hasUploaded(hazardDraft[f.fileKey]),
    );
    const nextDeclErrors: typeof declErrors = {};
    if (!classDraft) {
      nextDeclErrors.hazardClass = "Select the dangerous-goods class.";
    }
    if (!unDraft.trim()) nextDeclErrors.unNumber = "Enter the UN number.";

    setHazardErrors(
      Object.fromEntries(
        missing.map((f) => [f.fileKey, `${f.fileLabel} is required.`]),
      ),
    );
    setDeclErrors(nextDeclErrors);
    if (missing.length > 0 || Object.keys(nextDeclErrors).length > 0) return;

    form.setValue(
      "documents",
      {
        ...((form.getValues("documents") ?? {}) as ContractDocuments),
        ...hazardDraft,
      },
      { shouldDirty: true },
    );
    form.setValue("hazardClass", classDraft!, { shouldDirty: true });
    form.setValue("unNumber", unDraft.trim().toUpperCase(), {
      shouldDirty: true,
    });
    form.clearErrors(["hazardClass", "unNumber"]);
    form.setValue("isHazardous", true, { shouldDirty: true });
    setHazardModalOpen(false);
  };

  /** Turning the switch off drops the declaration with the documents. */
  const clearHazardDeclaration = () => {
    form.setValue("hazardClass", "", { shouldDirty: true });
    form.setValue("unNumber", "", { shouldDirty: true });
    form.clearErrors(["hazardClass", "unNumber"]);
  };

  // A hidden flag must never leak into the payload: a general contract can't be
  // hazardous, and a non-import contract carries neither reefer nor empty return.
  useEffect(() => {
    if (isOneTime) return;
    if (form.getValues("isHazardous")) {
      form.setValue("isHazardous", false, { shouldDirty: true });
      clearHazardDeclaration();
    }
    // Runs again once the hazard field list loads — a no-op when nothing matches.
    clearHazardDocs();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isOneTime, hazardKeys, form]);

  useEffect(() => {
    // Reefer has no switch right now, so it must never leave the form true.
    if (form.getValues("isRefrigerated")) {
      form.setValue("isRefrigerated", false, { shouldDirty: true });
    }
    if (isImport) return;
    if (form.getValues("equipmentReturn") === "with_return") {
      form.setValue("equipmentReturn", "without_return", { shouldDirty: true });
    }
  }, [isImport, form]);

  // Reset the commodity child only when the parent group really changes.
  const prevParentIdRef = useRef<string | undefined>(parentId);
  useEffect(() => {
    if (prevParentIdRef.current === parentId) return;
    const switchedToAnotherParent =
      !!prevParentIdRef.current && !!parentId;
    prevParentIdRef.current = parentId;
    if (switchedToAnotherParent) {
      form.setValue("cargoTypePath", [parentId as string, ""], {
        shouldDirty: true,
      });
    }
  }, [parentId, form]);

  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 (
      <div className="space-y-4">
        <Skeleton height={44} radius="md" />
        <Skeleton height={44} radius="md" />
        <Skeleton height={44} radius="md" />
      </div>
    );
  }

  return (
    <Stack gap={16}>
      <div className="grid gap-4 sm:grid-cols-2">
        <Controller
          name="cargoType"
          control={form.control}
          render={({ field, fieldState }) => (
            <Select
              label="Cargo Scope *"
              placeholder="Select cargo type…"
              data={CARGO_TYPE_OPTIONS}
              value={field.value || null}
              onChange={(v) => {
                if (!v) return;
                field.onChange(v);
                // cargoFreeText is the bulk commodity label — clear it so text
                // never carries across types (container description is captured
                // at booking time now).
                form.setValue("cargoFreeText", "", { shouldDirty: true });
                if (v === "container") {
                  form.setValue("cargoTypePath", [], { shouldDirty: true });
                  // Contracts always cover BOTH sizes; quantities are chosen per
                  // booking (a size can be 0 there).
                  form.setValue("enabledContainerSizes", [...CONTAINER_SIZES], {
                    shouldDirty: true,
                  });
                } else {
                  form.setValue("enabledContainerSizes", [], {
                    shouldDirty: true,
                  });
                }
              }}
              onBlur={field.onBlur}
              error={fieldState.error?.message}
              allowDeselect={false}
              radius={10}
              checkIconPosition="right"
              comboboxProps={{ withinPortal: true, shadow: "md", radius: "md" }}
              styles={fieldStyles}
            />
          )}
        />

      </div>

      {/* Container scope: the contract always covers BOTH sizes and quotes both
          rates. Quantities (a size can be 0) and the cargo description are
          captured at booking time. */}
      {cargoType === "container" && (
        <Group
          gap={13}
          align="center"
          wrap="nowrap"
          px={16}
          py={13}
          style={{
            borderRadius: 14,
            border: "1.5px solid #CDEBDD",
            background: "#F6FBF8",
          }}
        >
          <Box
            style={{
              width: 38,
              height: 38,
              borderRadius: 11,
              flexShrink: 0,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              background: "#EAF6EC",
              color: "#1E7B34",
            }}
          >
            <Container size={18} />
          </Box>
          <Box>
            <Text fz={14} fw={700} c="#10202F">
              20ft &amp; 40ft containers covered
            </Text>
            <Text fz={12} c="#6B7C8E" style={{ lineHeight: 1.4 }}>
              This contract quotes rates for both sizes. You choose the
              quantities on each booking — either size can be 0.
            </Text>
          </Box>
        </Group>
      )}

      {/* Bulk scope: a single commodity (cargo type path). No tonnage. */}
      {cargoType === "bulk" && (
        <Stack gap={12} mt={18}>
          {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}
                />
              )}
            />
          )}

        </Stack>
      )}

      {/* GENERAL contracts are uncapped — no quantity cap is collected. The
          customer / GL can book repeatedly against the contract until its
          validity expires (backend stores quantityCap = NULL = uncapped). */}

      {/* Shared billing flags. */}
      <Box>
        <StepLabel>Cargo handling</StepLabel>
        <Stack gap={12} mt={12}>
          {/* Hazardous cargo is only carried under a one-time contract, and
              enabling it requires the configured hazard documents up front. */}
          {isOneTime && (
            <Controller
              name="isHazardous"
              control={form.control}
              render={({ field }) => (
                <Stack gap={0}>
                  <ToggleRow
                    icon={<Flame size={18} />}
                    iconBg="#FBEAE7"
                    iconColor="#C0392B"
                    title="Hazardous Material"
                    description="Applies a hazard surcharge as a per-container unit rate. Requires a UN class, UN number and hazard documents."
                    checked={field.value ?? false}
                    onChange={(v) => {
                      if (v) {
                        openHazardModal();
                        return;
                      }
                      field.onChange(false);
                      clearHazardDocs();
                      clearHazardDeclaration();
                    }}
                  />
                  {field.value && (
                    <HazardDeclarationSummary
                      hazardClass={hazardClass}
                      unNumber={unNumber}
                      onEdit={openHazardModal}
                    />
                  )}
                </Stack>
              )}
            />
          )}
          {!isOneTime && (
            <AlertBox tone="info">
              Hazardous material can only be declared on a one-time contract.
              Switch <strong>Contract Kind</strong> to one-time to carry
              hazardous cargo.
            </AlertBox>
          )}
          {/* Refrigerated cargo is hidden for now — import-only when re-enabled.
              The effect above keeps isRefrigerated false while it's off.
          {isImport && (
            <Controller
              name="isRefrigerated"
              control={form.control}
              render={({ field }) => (
                <ToggleRow
                  icon={<Snowflake size={18} />}
                  iconBg="#E9F0F8"
                  iconColor="#2E5B96"
                  title="Refrigerated Cargo"
                  description="Temperature-controlled transport applies a reefer surcharge."
                  checked={field.value ?? false}
                  onChange={(v) => field.onChange(v)}
                />
              )}
            />
          )} */}
          {/* Empty-container return is a container-only IMPORT service. Like
              hazardous, enabling it here adds the return surcharge as a unit
              rate; at booking time the customer/GL sets how many return. */}
          {isImport && cargoType === "container" && (
            <Controller
              name="equipmentReturn"
              control={form.control}
              render={({ field }) => (
                <ToggleRow
                  icon={<RotateCcw size={18} />}
                  iconBg="#EAF6EC"
                  iconColor="#1E7B34"
                  title="Empty Container Return"
                  description="EDR returns the empty containers — applies a per-container return surcharge."
                  checked={field.value === "with_return"}
                  onChange={(v) =>
                    field.onChange(v ? "with_return" : "without_return")
                  }
                />
              )}
            />
          )}
        </Stack>
      </Box>

      <Modal
        opened={hazardModalOpen}
        onClose={() => setHazardModalOpen(false)}
        title={
          <Group gap={10} align="center" wrap="nowrap">
            <Box
              style={{
                width: 32,
                height: 32,
                borderRadius: 10,
                flexShrink: 0,
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                background: "#FBEAE7",
                color: "#C0392B",
              }}
            >
              <Flame size={16} />
            </Box>
            <Text fw={700} fz={15} c="#10202F">
              Hazardous cargo declaration
            </Text>
          </Group>
        }
        size="lg"
        centered
        radius={14}
      >
        <Stack gap={18}>
          <Text fz={13} c="#6B7C8E">
            Dangerous goods move only once the class and UN number are declared
            and the documents below are attached to the contract. EDR reviews
            this declaration in two dedicated hazardous approval steps.
          </Text>

          <Stack gap={12}>
            <StepLabel>Dangerous-goods declaration</StepLabel>
            <div className="grid gap-4 sm:grid-cols-2">
              <Select
                label="UN / ADR class *"
                placeholder="Select the hazard class…"
                data={HAZARD_CLASSES.map((c) => ({
                  value: c.value,
                  label: c.label,
                }))}
                value={classDraft}
                onChange={(v) => {
                  setClassDraft(v);
                  setDeclErrors((e) => ({ ...e, hazardClass: undefined }));
                }}
                error={declErrors.hazardClass}
                allowDeselect={false}
                radius={10}
                checkIconPosition="right"
                comboboxProps={{
                  withinPortal: true,
                  shadow: "md",
                  radius: "md",
                }}
                styles={fieldStyles}
              />
              <TextInput
                label="UN number *"
                placeholder="e.g. 1203"
                description="The four-digit UN number of the dangerous good."
                value={unDraft}
                onChange={(e) => {
                  setUnDraft(e.currentTarget.value);
                  setDeclErrors((err) => ({ ...err, unNumber: undefined }));
                }}
                error={declErrors.unNumber}
                radius={10}
                styles={fieldStyles}
              />
            </div>
          </Stack>

          <StepLabel>Hazard documents</StepLabel>

          {hazardSettingQuery.isLoading ? (
            <Group justify="center" py="lg">
              <Loader size="sm" color="edr-green" />
            </Group>
          ) : hazardFields.length > 0 && hazardSettingQuery.data ? (
            <SmartFileInput
              file={hazardSettingQuery.data}
              value={hazardDraft}
              onChange={(v) => setHazardDraft(v)}
              errors={hazardErrors}
            />
          ) : (
            <Text fz={13} c="#6B7C8E">
              No hazardous document requirements are configured yet. You can
              still flag the cargo as hazardous — EDR will request the paperwork
              during review.
            </Text>
          )}

          <Group justify="flex-end" gap={10}>
            <Button
              variant="default"
              radius={10}
              onClick={() => setHazardModalOpen(false)}
            >
              Cancel
            </Button>
            <Button color="edr-green" radius={10} onClick={confirmHazardDocs}>
              Save declaration
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Stack>
  );
}

/**
 * Reads back the saved dangerous-goods declaration under the hazard switch, so
 * the customer can see (and fix) the class + UN number without reopening the
 * modal blind. Rendered only while the contract is flagged hazardous.
 */
function HazardDeclarationSummary({
  hazardClass,
  unNumber,
  onEdit,
}: {
  hazardClass?: string;
  unNumber?: string;
  onEdit: () => void;
}) {
  const label = hazardClassLabel(hazardClass);
  return (
    <Group
      justify="space-between"
      align="center"
      wrap="nowrap"
      gap="sm"
      px={16}
      py={11}
      mt={-1}
      style={{
        borderRadius: "0 0 14px 14px",
        border: "1.5px solid #F3D5D0",
        borderTop: "none",
        background: "#FEF7F6",
      }}
    >
      <Group gap={8} align="center" wrap="wrap" style={{ minWidth: 0 }}>
        <Badge color="red" variant="light" radius="sm" size="sm">
          {label ?? "Class not set"}
        </Badge>
        <Badge color="red" variant="light" radius="sm" size="sm">
          {unNumber ? `UN ${unNumber}` : "UN number not set"}
        </Badge>
      </Group>
      <Button
        variant="subtle"
        color="red"
        size="compact-sm"
        radius={8}
        onClick={onEdit}
        style={{ flexShrink: 0 }}
      >
        Edit
      </Button>
    </Group>
  );
}

function ToggleRow({
  icon,
  iconBg,
  iconColor,
  title,
  description,
  checked,
  onChange,
}: {
  icon: React.ReactNode;
  iconBg: string;
  iconColor: string;
  title: string;
  description: string;
  checked: boolean;
  onChange: (v: boolean) => void;
}) {
  return (
    <Group
      justify="space-between"
      align="center"
      wrap="nowrap"
      px={16}
      py={13}
      style={{
        borderRadius: 14,
        border: `1.5px solid ${checked ? "#CDEBDD" : "#E6ECF2"}`,
        background: checked ? "#F6FBF8" : "#fff",
        transition: "all 150ms ease",
      }}
    >
      <Group gap={13} align="center" wrap="nowrap">
        <Box
          style={{
            width: 38,
            height: 38,
            borderRadius: 11,
            flexShrink: 0,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            background: iconBg,
            color: iconColor,
          }}
        >
          {icon}
        </Box>
        <Box>
          <Text fz={14} fw={700} c="#10202F">
            {title}
          </Text>
          <Text fz={12} c="#6B7C8E" style={{ lineHeight: 1.4 }}>
            {description}
          </Text>
        </Box>
      </Group>
      <Switch
        checked={checked}
        onChange={(e) => onChange(e.currentTarget.checked)}
        color="edr-green"
        size="md"
      />
    </Group>
  );
}
