import type { CreateBookingPayload } from "./bookings.service";
import { BOOKING_DOCS_SETTING, type BookingDocuments } from "@/pages/bookings/new-booking-form/schema";

function appendValue(formData: FormData, key: string, value: unknown) {
  if (value === undefined || value === null) return;
  if (typeof value === "boolean") {
    formData.append(key, value ? "true" : "false");
    return;
  }
  if (typeof value === "number") {
    formData.append(key, String(value));
    return;
  }
  if (typeof value === "string") {
    formData.append(key, value);
    return;
  }
}

function appendContainers(
  formData: FormData,
  containers: NonNullable<CreateBookingPayload["containers"]>,
) {
  containers.forEach((container, index) => {
    formData.append(
      `containers[${index}][containerTypeId]`,
      container.containerTypeId,
    );
    formData.append(
      `containers[${index}][quantity]`,
      String(container.quantity),
    );
    formData.append(
      `containers[${index}][vgmPerUnitTons]`,
      String(container.vgmPerUnitTons),
    );
  });
}

function appendDocuments(
  formData: FormData,
  documents?: Record<string, File | File[] | null>,
) {
  if (!documents) return;
  for (const [key, fileOrFiles] of Object.entries(documents)) {
    if (!fileOrFiles) continue;
    if (Array.isArray(fileOrFiles)) {
      for (const file of fileOrFiles) {
        formData.append(key, file);
      }
    } else {
      formData.append(key, fileOrFiles);
    }
  }
}

/** Flatten a booking payload (and optional document files) into multipart FormData. */
export function buildBookingFormData(
  payload: Partial<CreateBookingPayload>,
  documents?: BookingDocuments,
): FormData {
  const formData = new FormData();
  const skipKeys = new Set(["containers", "freightShapeValidation"]);

  for (const [key, value] of Object.entries(payload)) {
    if (skipKeys.has(key)) continue;
    appendValue(formData, key, value);
  }

  if (payload.containers?.length) {
    appendContainers(formData, payload.containers);
  }

  appendDocuments(formData, documents);
  return formData;
}

/** Returns true when every required booking document field has a file attached. */
export function hasAllRequiredDocuments(
  documents: BookingDocuments | undefined | null,
): boolean {
  const docs = documents ?? {};
  return BOOKING_DOCS_SETTING.fields.every((field) => {
    const value = docs[field.fileKey];
    if (Array.isArray(value)) return value.length > 0;
    return Boolean(value);
  });
}
