/**
 * MSC Request/Response Mapper
 *
 * Maps between internal domain format and MSC API format
 */

import { Injectable } from '@nestjs/common';
import { CarrierRateSearchInput } from '@domain/ports/out/carrier-connector.port';
import { RateQuote, RouteSegment, Surcharge } from '@domain/entities/rate-quote.entity';
import { v4 as uuidv4 } from 'uuid';

@Injectable()
export class MSCRequestMapper {
  /**
   * Map internal format to MSC API request format
   */
  toMSCRequest(input: CarrierRateSearchInput): any {
    return {
      pol: input.origin, // Port of Loading
      pod: input.destination, // Port of Discharge
      container_type: this.mapContainerType(input.containerType),
      cargo_ready_date: input.departureDate,
      service_mode: input.mode === 'FCL' ? 'FCL' : 'LCL',
      commodity_code: 'FAK', // Freight All Kinds (default)
      is_dangerous: input.isHazmat || false,
      imo_class: input.imoClass,
      weight_kg: input.weight,
      volume_cbm: input.volume,
    };
  }

  /**
   * Map MSC response to domain RateQuote entities
   */
  fromMSCResponse(mscResponse: any, originalInput: CarrierRateSearchInput): RateQuote[] {
    if (!mscResponse.quotes || mscResponse.quotes.length === 0) {
      return [];
    }

    return mscResponse.quotes.map((quote: any) => {
      // Calculate surcharges
      const surcharges: Surcharge[] = [
        {
          type: 'BAF',
          description: 'Bunker Adjustment Factor',
          amount: quote.surcharges?.baf || 0,
          currency: quote.currency || 'USD',
        },
        {
          type: 'CAF',
          description: 'Currency Adjustment Factor',
          amount: quote.surcharges?.caf || 0,
          currency: quote.currency || 'USD',
        },
        {
          type: 'PSS',
          description: 'Peak Season Surcharge',
          amount: quote.surcharges?.pss || 0,
          currency: quote.currency || 'USD',
        },
      ].filter(s => s.amount > 0);

      const totalSurcharges = surcharges.reduce((sum, s) => sum + s.amount, 0);
      const baseFreight = quote.ocean_freight || 0;
      const totalAmount = baseFreight + totalSurcharges;

      // Build route segments
      const route: RouteSegment[] = [];

      // Origin port
      route.push({
        portCode: originalInput.origin,
        portName: quote.pol_name || originalInput.origin,
        departure: new Date(quote.etd),
        vesselName: quote.vessel_name,
        voyageNumber: quote.voyage_number,
      });

      // Transshipment ports
      if (quote.via_ports && Array.isArray(quote.via_ports)) {
        quote.via_ports.forEach((port: any) => {
          route.push({
            portCode: port.code || port,
            portName: port.name || port.code || port,
          });
        });
      }

      // Destination port
      route.push({
        portCode: originalInput.destination,
        portName: quote.pod_name || originalInput.destination,
        arrival: new Date(quote.eta),
      });

      const transitDays = quote.transit_days || this.calculateTransitDays(quote.etd, quote.eta);

      // Create rate quote
      return RateQuote.create({
        id: uuidv4(),
        carrierId: 'msc',
        carrierName: 'MSC',
        carrierCode: 'MSCU',
        origin: {
          code: originalInput.origin,
          name: quote.pol_name || originalInput.origin,
          country: quote.pol_country || 'Unknown',
        },
        destination: {
          code: originalInput.destination,
          name: quote.pod_name || originalInput.destination,
          country: quote.pod_country || 'Unknown',
        },
        pricing: {
          baseFreight,
          surcharges,
          totalAmount,
          currency: quote.currency || 'USD',
        },
        containerType: originalInput.containerType,
        mode: (originalInput.mode as 'FCL' | 'LCL') || 'FCL',
        etd: new Date(quote.etd),
        eta: new Date(quote.eta),
        transitDays,
        route,
        availability: quote.available_slots || 0,
        frequency: quote.frequency || 'Weekly',
        vesselType: 'Container Ship',
        co2EmissionsKg: quote.co2_kg,
      });
    });
  }

  /**
   * Map internal container type to MSC format
   */
  private mapContainerType(type: string): string {
    const mapping: Record<string, string> = {
      '20GP': '20DC',
      '40GP': '40DC',
      '40HC': '40HC',
      '45HC': '45HC',
      '20RF': '20RF',
      '40RF': '40RF',
    };
    return mapping[type] || type;
  }

  /**
   * Calculate transit days from ETD and ETA
   */
  private calculateTransitDays(etd: string, eta: string): number {
    const etdDate = new Date(etd);
    const etaDate = new Date(eta);
    const diff = etaDate.getTime() - etdDate.getTime();
    return Math.ceil(diff / (1000 * 60 * 60 * 24));
  }
}
