import type { ContainerPlacementInput } from './wagon-plan.util';

export type ContainerUnitForPlacement = {
  bookingId: string;
  bookingReference?: string | null;
  bookingContainerId: string;
  unitIndex: number;
  label: string;
  teuSlots?: number;
  sizeFt?: number;
  containerNumber?: string | null;
};

export function placeholderContainerNumber(unit: ContainerUnitForPlacement): string {
  const ref = unit.bookingReference ?? unit.bookingId.slice(0, 8);
  return `TBD-${ref}-${unit.unitIndex + 1}`;
}

export function isPlaceholderContainerNumber(value: string | null | undefined): boolean {
  return Boolean(value?.trim().startsWith('TBD-'));
}

export function resolveContainerNumber(unit: ContainerUnitForPlacement): string {
  const trimmed = unit.containerNumber?.trim();
  return trimmed || placeholderContainerNumber(unit);
}

export function autoFillPlacements(
  units: ContainerUnitForPlacement[],
  containerSlots: number[],
): ContainerPlacementInput[] {
  if (!units.length || !containerSlots.length) return [];

  const placements: ContainerPlacementInput[] = [];
  const MAX_TEU_PER_WAGON = 2;
  let currentSlotIndex = 0;
  let teuInCurrentSlot = 0;

  for (const unit of units) {
    const teu = unit.teuSlots ?? (unit.sizeFt && unit.sizeFt >= 40 ? 2 : 1);

    if (teuInCurrentSlot > 0 && teuInCurrentSlot + teu > MAX_TEU_PER_WAGON) {
      currentSlotIndex += 1;
      teuInCurrentSlot = 0;
    }

    const sequenceNo =
      containerSlots[Math.min(currentSlotIndex, containerSlots.length - 1)] ??
      containerSlots[containerSlots.length - 1] ??
      containerSlots[0];

    placements.push({
      bookingContainerId: unit.bookingContainerId,
      unitIndex: unit.unitIndex,
      sequenceNo,
      containerNumber: resolveContainerNumber(unit),
    });

    teuInCurrentSlot += teu;
  }

  return placements;
}

export function findMissingContainerNumberIssues(
  units: ContainerUnitForPlacement[],
  placements: ContainerPlacementInput[],
): Array<{ bookingId: string; issue: string }> {
  const issues: Array<{ bookingId: string; issue: string }> = [];
  const byUnit = new Map(
    placements.map((p) => [`${p.bookingContainerId}:${p.unitIndex}`, p]),
  );

  for (const unit of units) {
    const placement = byUnit.get(`${unit.bookingContainerId}:${unit.unitIndex}`);
    if (!placement?.containerNumber?.trim()) {
      issues.push({
        bookingId: unit.bookingId,
        issue: `Missing container number for ${unit.label}`,
      });
    }
  }

  return issues;
}

export function placementsForBookings(
  placements: ContainerPlacementInput[],
  bookingIds: Set<string>,
  units: ContainerUnitForPlacement[],
): ContainerPlacementInput[] {
  const unitBookingIds = new Map(
    units.map((u) => [`${u.bookingContainerId}:${u.unitIndex}`, u.bookingId]),
  );
  return placements.filter((p) => {
    const bookingId = unitBookingIds.get(`${p.bookingContainerId}:${p.unitIndex}`);
    return bookingId ? bookingIds.has(bookingId) : false;
  });
}
