/**
 * CMA CGM Request/Response Mapper
 */

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 CMACGMRequestMapper {
  toCMACGMRequest(input: CarrierRateSearchInput): any {
    return {
      departure_port_locode: input.origin,
      arrival_port_locode: input.destination,
      equipment_type_code: this.mapContainerType(input.containerType),
      cargo_ready_date: input.departureDate,
      shipment_term: input.mode,
      cargo_type: input.isHazmat ? 'HAZARDOUS' : 'GENERAL',
      imo_class: input.imoClass,
      gross_weight_kg: input.weight,
      volume_cbm: input.volume,
    };
  }

  fromCMACGMResponse(cgmResponse: any, originalInput: CarrierRateSearchInput): RateQuote[] {
    if (!cgmResponse.quotations || cgmResponse.quotations.length === 0) {
      return [];
    }

    return cgmResponse.quotations.map((quotation: any) => {
      const surcharges: Surcharge[] = [
        {
          type: 'BAF',
          description: 'Bunker Surcharge',
          amount: quotation.charges?.bunker_surcharge || 0,
          currency: quotation.charges?.currency || 'USD',
        },
        {
          type: 'CAF',
          description: 'Currency Surcharge',
          amount: quotation.charges?.currency_surcharge || 0,
          currency: quotation.charges?.currency || 'USD',
        },
        {
          type: 'PSS',
          description: 'Peak Season',
          amount: quotation.charges?.peak_season || 0,
          currency: quotation.charges?.currency || 'USD',
        },
        {
          type: 'THC',
          description: 'Terminal Handling',
          amount: quotation.charges?.thc || 0,
          currency: quotation.charges?.currency || 'USD',
        },
      ].filter(s => s.amount > 0);

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

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

      // Origin port
      route.push({
        portCode: originalInput.origin,
        portName: quotation.routing?.departure_port_name || originalInput.origin,
        departure: new Date(quotation.schedule?.departure_date),
        vesselName: quotation.vessel?.name,
        voyageNumber: quotation.vessel?.voyage,
      });

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

      // Destination port
      route.push({
        portCode: originalInput.destination,
        portName: quotation.routing?.arrival_port_name || originalInput.destination,
        arrival: new Date(quotation.schedule?.arrival_date),
      });

      const transitDays =
        quotation.schedule?.transit_time_days ||
        this.calculateTransitDays(
          quotation.schedule?.departure_date,
          quotation.schedule?.arrival_date
        );

      return RateQuote.create({
        id: uuidv4(),
        carrierId: 'cmacgm',
        carrierName: 'CMA CGM',
        carrierCode: 'CMDU',
        origin: {
          code: originalInput.origin,
          name: quotation.routing?.departure_port_name || originalInput.origin,
          country: quotation.routing?.departure_country || 'Unknown',
        },
        destination: {
          code: originalInput.destination,
          name: quotation.routing?.arrival_port_name || originalInput.destination,
          country: quotation.routing?.arrival_country || 'Unknown',
        },
        pricing: {
          baseFreight,
          surcharges,
          totalAmount,
          currency: quotation.charges?.currency || 'USD',
        },
        containerType: originalInput.containerType,
        mode: (originalInput.mode as 'FCL' | 'LCL') || 'FCL',
        etd: new Date(quotation.schedule?.departure_date),
        eta: new Date(quotation.schedule?.arrival_date),
        transitDays,
        route,
        availability: quotation.capacity?.slots_available || 0,
        frequency: quotation.service?.frequency || 'Weekly',
        vesselType: 'Container Ship',
        co2EmissionsKg: quotation.environmental?.co2_kg,
      });
    });
  }

  private mapContainerType(type: string): string {
    const mapping: Record<string, string> = {
      '20GP': '22G1',
      '40GP': '42G1',
      '40HC': '45G1',
      '45HC': '45G1',
      '20RF': '22R1',
      '40RF': '42R1',
    };
    return mapping[type] || type;
  }

  private calculateTransitDays(departure?: string, arrival?: string): number {
    if (!departure || !arrival) return 0;
    const depDate = new Date(departure);
    const arrDate = new Date(arrival);
    const diff = arrDate.getTime() - depDate.getTime();
    return Math.ceil(diff / (1000 * 60 * 60 * 24));
  }
}
