import { Booking } from '@domain/entities/booking.entity';
import { RateQuote } from '@domain/entities/rate-quote.entity';
import { BookingResponseDto, BookingListItemDto } from '../dto/booking-response.dto';
import { CreateBookingRequestDto } from '../dto/create-booking-request.dto';

export class BookingMapper {
  /**
   * Map CreateBookingRequestDto to domain inputs
   */
  static toCreateBookingInput(dto: CreateBookingRequestDto) {
    return {
      rateQuoteId: dto.rateQuoteId,
      shipper: {
        name: dto.shipper.name,
        address: {
          street: dto.shipper.address.street,
          city: dto.shipper.address.city,
          postalCode: dto.shipper.address.postalCode,
          country: dto.shipper.address.country,
        },
        contactName: dto.shipper.contactName,
        contactEmail: dto.shipper.contactEmail,
        contactPhone: dto.shipper.contactPhone,
      },
      consignee: {
        name: dto.consignee.name,
        address: {
          street: dto.consignee.address.street,
          city: dto.consignee.address.city,
          postalCode: dto.consignee.address.postalCode,
          country: dto.consignee.address.country,
        },
        contactName: dto.consignee.contactName,
        contactEmail: dto.consignee.contactEmail,
        contactPhone: dto.consignee.contactPhone,
      },
      cargoDescription: dto.cargoDescription,
      containers: dto.containers.map(c => ({
        type: c.type,
        containerNumber: c.containerNumber,
        vgm: c.vgm,
        temperature: c.temperature,
        sealNumber: c.sealNumber,
      })),
      specialInstructions: dto.specialInstructions,
    };
  }

  /**
   * Map Booking entity and RateQuote to BookingResponseDto
   */
  static toDto(booking: Booking, rateQuote: RateQuote): BookingResponseDto {
    return {
      id: booking.id,
      bookingNumber: booking.bookingNumber.value,
      status: booking.status.value,
      shipper: {
        name: booking.shipper.name,
        address: {
          street: booking.shipper.address.street,
          city: booking.shipper.address.city,
          postalCode: booking.shipper.address.postalCode,
          country: booking.shipper.address.country,
        },
        contactName: booking.shipper.contactName,
        contactEmail: booking.shipper.contactEmail,
        contactPhone: booking.shipper.contactPhone,
      },
      consignee: {
        name: booking.consignee.name,
        address: {
          street: booking.consignee.address.street,
          city: booking.consignee.address.city,
          postalCode: booking.consignee.address.postalCode,
          country: booking.consignee.address.country,
        },
        contactName: booking.consignee.contactName,
        contactEmail: booking.consignee.contactEmail,
        contactPhone: booking.consignee.contactPhone,
      },
      cargoDescription: booking.cargoDescription,
      containers: booking.containers.map(c => ({
        id: c.id,
        type: c.type,
        containerNumber: c.containerNumber,
        vgm: c.vgm,
        temperature: c.temperature,
        sealNumber: c.sealNumber,
      })),
      specialInstructions: booking.specialInstructions,
      rateQuote: {
        id: rateQuote.id,
        carrierName: rateQuote.carrierName,
        carrierCode: rateQuote.carrierCode,
        origin: {
          code: rateQuote.origin.code,
          name: rateQuote.origin.name,
          country: rateQuote.origin.country,
        },
        destination: {
          code: rateQuote.destination.code,
          name: rateQuote.destination.name,
          country: rateQuote.destination.country,
        },
        pricing: {
          baseFreight: rateQuote.pricing.baseFreight,
          surcharges: rateQuote.pricing.surcharges.map(s => ({
            type: s.type,
            description: s.description,
            amount: s.amount,
            currency: s.currency,
          })),
          totalAmount: rateQuote.pricing.totalAmount,
          currency: rateQuote.pricing.currency,
        },
        containerType: rateQuote.containerType,
        mode: rateQuote.mode,
        etd: rateQuote.etd.toISOString(),
        eta: rateQuote.eta.toISOString(),
        transitDays: rateQuote.transitDays,
      },
      createdAt: booking.createdAt.toISOString(),
      updatedAt: booking.updatedAt.toISOString(),
    };
  }

  /**
   * Map Booking entity to list item DTO (simplified view)
   */
  static toListItemDto(booking: Booking, rateQuote: RateQuote): BookingListItemDto {
    return {
      id: booking.id,
      bookingNumber: booking.bookingNumber.value,
      status: booking.status.value,
      shipperName: booking.shipper.name,
      consigneeName: booking.consignee.name,
      originPort: rateQuote.origin.code,
      destinationPort: rateQuote.destination.code,
      carrierName: rateQuote.carrierName,
      etd: rateQuote.etd.toISOString(),
      eta: rateQuote.eta.toISOString(),
      totalAmount: rateQuote.pricing.totalAmount,
      currency: rateQuote.pricing.currency,
      createdAt: booking.createdAt.toISOString(),
    };
  }

  /**
   * Map array of bookings to list item DTOs
   */
  static toListItemDtoArray(
    bookings: Array<{ booking: Booking; rateQuote: RateQuote }>
  ): BookingListItemDto[] {
    return bookings.map(({ booking, rateQuote }) => this.toListItemDto(booking, rateQuote));
  }
}
