/**
 * Maersk Connector
 *
 * Implementation of CarrierConnectorPort for Maersk API
 */

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { BaseCarrierConnector, CarrierConfig } from '../base-carrier.connector';
import {
  CarrierRateSearchInput,
  CarrierAvailabilityInput,
} from '@domain/ports/out/carrier-connector.port';
import { RateQuote } from '@domain/entities/rate-quote.entity';
import { MaerskRequestMapper } from './maersk-request.mapper';
import { MaerskResponseMapper } from './maersk-response.mapper';
import { MaerskRateSearchResponse } from './maersk.types';

@Injectable()
export class MaerskConnector extends BaseCarrierConnector {
  constructor(private readonly configService: ConfigService) {
    const config: CarrierConfig = {
      name: 'Maersk',
      code: 'MAERSK',
      baseUrl: configService.get<string>('MAERSK_API_BASE_URL', 'https://api.maersk.com/v1'),
      timeout: 5000, // 5 seconds
      maxRetries: 2,
      circuitBreakerThreshold: 50, // Open circuit after 50% failures
      circuitBreakerTimeout: 30000, // Wait 30s before half-open
    };

    super(config);
  }

  async searchRates(input: CarrierRateSearchInput): Promise<RateQuote[]> {
    try {
      // Map domain input to Maersk API format
      const maerskRequest = MaerskRequestMapper.toMaerskRateSearchRequest(input);

      // Make API request with circuit breaker
      const response = await this.requestWithCircuitBreaker<MaerskRateSearchResponse>({
        method: 'POST',
        url: '/rates/search',
        data: maerskRequest,
        headers: {
          'API-Key': this.configService.get<string>('MAERSK_API_KEY'),
        },
      });

      // Map Maersk API response to domain entities
      const rateQuotes = MaerskResponseMapper.toRateQuotes(
        response.data,
        input.origin,
        input.destination
      );

      this.logger.log(`Found ${rateQuotes.length} rate quotes from Maersk`);
      return rateQuotes;
    } catch (error: any) {
      this.logger.error(`Error searching Maersk rates: ${error?.message || 'Unknown error'}`);
      // Return empty array instead of throwing - allows other carriers to succeed
      return [];
    }
  }

  async checkAvailability(input: CarrierAvailabilityInput): Promise<number> {
    try {
      const response = await this.requestWithCircuitBreaker<{ availability: number }>({
        method: 'POST',
        url: '/availability/check',
        data: {
          origin: input.origin,
          destination: input.destination,
          containerType: input.containerType,
          departureDate: input.departureDate?.toISOString() || input.startDate.toISOString(),
          quantity: input.quantity,
        },
        headers: {
          'API-Key': this.configService.get<string>('MAERSK_API_KEY'),
        },
      });

      return response.data.availability;
    } catch (error: any) {
      this.logger.error(`Error checking Maersk availability: ${error?.message || 'Unknown error'}`);
      return 0;
    }
  }

  /**
   * Override health check to use Maersk-specific endpoint
   */
  async healthCheck(): Promise<boolean> {
    try {
      await this.requestWithCircuitBreaker({
        method: 'GET',
        url: '/status',
        timeout: 3000,
        headers: {
          'API-Key': this.configService.get<string>('MAERSK_API_KEY'),
        },
      });
      return true;
    } catch (error: any) {
      this.logger.warn(`Maersk health check failed: ${error?.message || 'Unknown error'}`);
      return false;
    }
  }
}
