import {
  CsvBooking,
  CsvBookingStatus,
  CsvBookingDocument,
} from '@domain/entities/csv-booking.entity';
import { PortCode } from '@domain/value-objects/port-code.vo';
import { CsvBookingOrmEntity } from '../entities/csv-booking.orm-entity';

/**
 * CSV Booking Mapper
 *
 * Maps between domain CsvBooking entity and ORM entity
 */
export class CsvBookingMapper {
  /**
   * Map ORM entity to domain entity
   *
   * Uses fromPersistence to avoid validation errors when loading legacy data
   * that might have empty documents array
   */
  static toDomain(ormEntity: CsvBookingOrmEntity): CsvBooking {
    return CsvBooking.fromPersistence(
      ormEntity.id,
      ormEntity.userId,
      ormEntity.organizationId,
      ormEntity.carrierName,
      ormEntity.carrierEmail,
      PortCode.create(ormEntity.origin),
      PortCode.create(ormEntity.destination),
      Number(ormEntity.volumeCBM),
      Number(ormEntity.weightKG),
      ormEntity.palletCount,
      Number(ormEntity.priceUSD),
      Number(ormEntity.priceEUR),
      ormEntity.primaryCurrency,
      ormEntity.transitDays,
      ormEntity.containerType,
      CsvBookingStatus[ormEntity.status] as CsvBookingStatus,
      (ormEntity.documents || []) as CsvBookingDocument[], // Ensure documents is always an array
      ormEntity.confirmationToken,
      ormEntity.requestedAt,
      ormEntity.respondedAt,
      ormEntity.notes,
      ormEntity.rejectionReason,
      ormEntity.bookingNumber ?? undefined,
      ormEntity.commissionRate != null ? Number(ormEntity.commissionRate) : undefined,
      ormEntity.commissionAmountEur != null ? Number(ormEntity.commissionAmountEur) : undefined,
      ormEntity.stripePaymentIntentId ?? undefined
    );
  }

  /**
   * Map domain entity to ORM entity (for creation)
   */
  static toOrmCreate(domain: CsvBooking): Partial<CsvBookingOrmEntity> {
    return {
      id: domain.id,
      userId: domain.userId,
      organizationId: domain.organizationId,
      carrierName: domain.carrierName,
      carrierEmail: domain.carrierEmail,
      origin: domain.origin.getValue(),
      destination: domain.destination.getValue(),
      volumeCBM: domain.volumeCBM,
      weightKG: domain.weightKG,
      palletCount: domain.palletCount,
      priceUSD: domain.priceUSD,
      priceEUR: domain.priceEUR,
      primaryCurrency: domain.primaryCurrency,
      transitDays: domain.transitDays,
      containerType: domain.containerType,
      status: domain.status as CsvBookingOrmEntity['status'],
      documents: domain.documents as any,
      confirmationToken: domain.confirmationToken,
      requestedAt: domain.requestedAt,
      respondedAt: domain.respondedAt,
      notes: domain.notes,
      rejectionReason: domain.rejectionReason,
      stripePaymentIntentId: domain.stripePaymentIntentId ?? null,
      commissionRate: domain.commissionRate ?? null,
      commissionAmountEur: domain.commissionAmountEur ?? null,
    };
  }

  /**
   * Map domain entity to ORM entity (for update)
   */
  static toOrmUpdate(domain: CsvBooking): Partial<CsvBookingOrmEntity> {
    return {
      status: domain.status as CsvBookingOrmEntity['status'],
      respondedAt: domain.respondedAt,
      notes: domain.notes,
      rejectionReason: domain.rejectionReason,
      stripePaymentIntentId: domain.stripePaymentIntentId ?? null,
      commissionRate: domain.commissionRate ?? null,
      commissionAmountEur: domain.commissionAmountEur ?? null,
    };
  }

  /**
   * Map array of ORM entities to domain entities
   */
  static toDomainArray(ormEntities: CsvBookingOrmEntity[]): CsvBooking[] {
    return ormEntities.map(entity => this.toDomain(entity));
  }
}
