/**
 * CMA CGM Connector
 *
 * Implements CarrierConnectorPort for CMA CGM WebAccess API integration
 */

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
  CarrierConnectorPort,
  CarrierRateSearchInput,
  CarrierAvailabilityInput,
} from '@domain/ports/out/carrier-connector.port';
import { RateQuote } from '@domain/entities/rate-quote.entity';
import { BaseCarrierConnector, CarrierConfig } from '../base-carrier.connector';
import { CMACGMRequestMapper } from './cma-cgm.mapper';

@Injectable()
export class CMACGMConnectorAdapter extends BaseCarrierConnector implements CarrierConnectorPort {
  private readonly apiUrl: string;
  private readonly clientId: string;
  private readonly clientSecret: string;

  constructor(
    private readonly configService: ConfigService,
    private readonly requestMapper: CMACGMRequestMapper
  ) {
    const config: CarrierConfig = {
      name: 'CMA CGM',
      code: 'CMDU',
      baseUrl: configService.get<string>('CMACGM_API_URL', 'https://api.cma-cgm.com/v1'),
      timeout: 5000,
      maxRetries: 3,
      circuitBreakerThreshold: 50,
      circuitBreakerTimeout: 30000,
    };
    super(config);
    this.apiUrl = config.baseUrl;
    this.clientId = this.configService.get<string>('CMACGM_CLIENT_ID', '');
    this.clientSecret = this.configService.get<string>('CMACGM_CLIENT_SECRET', '');
  }

  async searchRates(input: CarrierRateSearchInput): Promise<RateQuote[]> {
    this.logger.log(`Searching CMA CGM rates: ${input.origin} -> ${input.destination}`);

    try {
      // Get OAuth token first
      const accessToken = await this.getAccessToken();

      // Map to CMA CGM format
      const cgmRequest = this.requestMapper.toCMACGMRequest(input);

      // Make API call
      const response = await this.makeRequest({
        url: `${this.apiUrl}/quotations/search`,
        method: 'POST',
        data: cgmRequest,
        headers: {
          Authorization: `Bearer ${accessToken}`,
          'Content-Type': 'application/json',
        },
      });

      // Map response to domain
      const rateQuotes = this.requestMapper.fromCMACGMResponse(response.data, input);

      this.logger.log(`Found ${rateQuotes.length} CMA CGM rates`);
      return rateQuotes;
    } catch (error: any) {
      this.logger.error(`CMA CGM API error: ${error?.message || 'Unknown error'}`);

      if (error?.response?.status === 401) {
        this.logger.error('CMA CGM authentication failed');
        throw new Error('CMACGM_AUTH_FAILED');
      }

      return [];
    }
  }

  async checkAvailability(input: CarrierAvailabilityInput): Promise<number> {
    try {
      const accessToken = await this.getAccessToken();

      const response = await this.makeRequest({
        url: `${this.apiUrl}/capacity/check`,
        method: 'POST',
        data: {
          departure_port: input.origin,
          arrival_port: input.destination,
          departure_date: input.departureDate,
          equipment_type: input.containerType,
          quantity: input.quantity,
        },
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      });

      return (response.data as any).capacity_available || 0;
    } catch (error: any) {
      this.logger.error(`CMA CGM availability check error: ${error?.message || 'Unknown error'}`);
      return 0;
    }
  }

  /**
   * Get OAuth access token
   */
  private async getAccessToken(): Promise<string> {
    // In production, implement token caching
    try {
      const response = await this.makeRequest({
        url: `${this.apiUrl}/oauth/token`,
        method: 'POST',
        data: {
          grant_type: 'client_credentials',
          client_id: this.clientId,
          client_secret: this.clientSecret,
        },
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
        },
      });

      return (response.data as any).access_token;
    } catch (error: any) {
      this.logger.error(`Failed to get CMA CGM access token: ${error?.message || 'Unknown error'}`);
      throw new Error('CMACGM_TOKEN_ERROR');
    }
  }
}
