import type { Freight } from "@edr/types";
import type { ContractFormInputValues, OperationType } from "./schema";
import { initialContractFormValues } from "./schema";

/**
 * Trade direction → base operation type. The freight-forwarder variants
 * (import_ff / export_ff) are selected by the caller when the contract is
 * stamped to a freight_forwarder profile (see `isForwarderProfile`).
 */
function directionToOperation(
  direction: Freight.ContractTradeDirection,
  isForwarderProfile: boolean,
): OperationType {
  if (direction === "IMPORT") return isForwarderProfile ? "import_ff" : "import";
  if (direction === "EXPORT") return isForwarderProfile ? "export_ff" : "export";
  return "intercity";
}

/**
 * Rebuild the cargo-type path `[groupId, commodityId]` from a flat cargoTypeId
 * by locating which reference cargo-type group owns it.
 */
function cargoTypePathFor(
  cargoTypeId: string | null | undefined,
  referenceData: Freight.BookingReferenceData | undefined,
): string[] {
  if (!cargoTypeId || !referenceData?.cargo_type) return [];
  for (const group of referenceData.cargo_type) {
    if (group.children?.some((c) => c.id === cargoTypeId)) {
      return [group.id, cargoTypeId];
    }
  }
  return [];
}

/**
 * Inverse of `buildApiPayload` in NewContractPage: hydrate the contract wizard
 * form from a saved contract so a customer can edit a CHANGES_REQUESTED (or
 * DRAFT) contract in the same UI used to create it. Missing fields fall back to
 * `initialContractFormValues`. Files are not mapped — the wizard's `documents`
 * map only holds freshly attached replacements; existing files are listed
 * separately by `ContractDocsEditor`.
 */
export function contractToFormValues(
  contract: Freight.IContract,
  referenceData: Freight.BookingReferenceData | undefined,
  isForwarderProfile: boolean,
): Partial<ContractFormInputValues> {
  const isContainer = contract.freightType === "CONTAINER";
  const isGeneral = contract.contractKind === "GENERAL";

  const routes = [...(contract.routes ?? [])].sort(
    (a, b) => a.sortOrder - b.sortOrder,
  );
  // Contracts carry a single route now; older multi-route GENERAL contracts
  // load only their primary route.
  const primaryRoute = routes[0];

  const scope = contract.cargoScope ?? [];

  // Container scope: contracts now always cover both sizes — force both even
  // for older single-size drafts so resubmitting upgrades them.
  const enabledContainerSizes = isContainer ? ["20ft", "40ft"] : [];
  const containerSizeCaps: Record<string, number> = {};
  if (isContainer && isGeneral) {
    for (const s of scope) {
      if (s.containerSize && s.quantityCap != null) {
        containerSizeCaps[s.containerSize] = s.quantityCap;
      }
    }
  }

  // Bulk scope: a single commodity row.
  const bulkRow = !isContainer ? scope[0] : undefined;
  const cargoTypePath = bulkRow
    ? cargoTypePathFor(bulkRow.cargoTypeId, referenceData)
    : [];

  const hasFirstMile = Boolean(contract.firstMilePickupAddress);
  const hasLastMile = Boolean(contract.lastMileDeliveryAddress);

  return {
    ...initialContractFormValues,

    operationType: directionToOperation(
      contract.tradeDirection,
      isForwarderProfile,
    ),
    contractKind: isGeneral ? "general_contract" : "one_time",
    contractType: contract.renewalOfId ? "renewal" : "new",
    previousContractRef: contract.renewalOfId ?? "",

    serviceTypeId: contract.serviceTypeId,

    firstMile: {
      enabled: hasFirstMile,
      pickUpAddress: contract.firstMilePickupAddress ?? "",
      exactLocation: "",
      lat: contract.firstMilePickupLat ?? null,
      lng: contract.firstMilePickupLng ?? null,
    },
    lastMile: {
      enabled: hasLastMile,
      deliveryAddress: contract.lastMileDeliveryAddress ?? "",
      exactLocation: "",
      lat: contract.lastMileDeliveryLat ?? null,
      lng: contract.lastMileDeliveryLng ?? null,
    },
    customsClearingEnabled: contract.customsClearingEnabled,
    customsClearingAgent: contract.customsClearingAgent ?? "",

    cargoType: isContainer ? "container" : "bulk",
    enabledContainerSizes:
      enabledContainerSizes as ContractFormInputValues["enabledContainerSizes"],
    containerSizeCaps,
    cargoTypePath,
    // Bulk commodity free-text only — the container cargo description is
    // captured per booking now, not on the contract.
    cargoFreeText: (isContainer ? "" : bulkRow?.cargoFreeText) ?? "",
    bulkQuantityCap:
      isGeneral && bulkRow?.quantityCap != null ? bulkRow.quantityCap : 0,
    isHazardous: contract.isHazardous,
    hazardClass: contract.hazardClass ?? "",
    unNumber: contract.unNumber ?? "",
    isRefrigerated: contract.isReefer,

    originYard: primaryRoute?.originYardId ?? "",
    destinationYard: primaryRoute?.destinationYardId ?? "",

    documents: {},
  };
}

export default contractToFormValues;
