import { CsvRate } from '../entities/csv-rate.entity';

export interface PriceCalculationParams {
  volumeCBM: number;
  weightKG: number;
  palletCount: number;
  hasDangerousGoods: boolean;
  requiresSpecialHandling: boolean;
  requiresTailgate: boolean;
  requiresStraps: boolean;
  requiresThermalCover: boolean;
  hasRegulatedProducts: boolean;
  requiresAppointment: boolean;
}

export interface PriceBreakdown {
  basePrice: number;
  volumeCharge: number;
  weightCharge: number;
  palletCharge: number;
  surcharges: SurchargeItem[];
  totalSurcharges: number;
  totalPrice: number;
  currency: string;
}

export interface SurchargeItem {
  code: string;
  description: string;
  amount: number;
  type: 'FIXED' | 'PER_UNIT' | 'PERCENTAGE';
}

/**
 * Service de calcul de prix pour les tarifs CSV
 * Calcule le prix total basé sur le volume, poids, palettes et services additionnels
 */
export class CsvRatePriceCalculatorService {
  /**
   * Calcule le prix total pour un tarif CSV donné
   */
  calculatePrice(rate: CsvRate, params: PriceCalculationParams): PriceBreakdown {
    // 1. Prix de base
    const basePrice = rate.pricing.basePriceUSD.getAmount();

    // 2. Frais au volume (USD par CBM)
    const volumeCharge = rate.pricing.pricePerCBM * params.volumeCBM;

    // 3. Frais au poids (USD par KG)
    const weightCharge = rate.pricing.pricePerKG * params.weightKG;

    // 4. Frais de palettes (25 USD par palette)
    const palletCharge = params.palletCount * 25;

    // 5. Surcharges standard du CSV
    const standardSurcharges = this.parseStandardSurcharges(rate.getSurchargeDetails(), params);

    // 6. Surcharges additionnelles basées sur les services
    const additionalSurcharges = this.calculateAdditionalSurcharges(params);

    // 7. Total des surcharges
    const allSurcharges = [...standardSurcharges, ...additionalSurcharges];
    const totalSurcharges = allSurcharges.reduce((sum, s) => sum + s.amount, 0);

    // 8. Prix total
    const totalPrice = basePrice + volumeCharge + weightCharge + palletCharge + totalSurcharges;

    return {
      basePrice,
      volumeCharge,
      weightCharge,
      palletCharge,
      surcharges: allSurcharges,
      totalSurcharges,
      totalPrice: Math.round(totalPrice * 100) / 100, // Arrondi à 2 décimales
      currency: rate.currency || 'USD',
    };
  }

  /**
   * Parse les surcharges standard du format CSV
   * Format: "DOC:10 | ISPS:7 | HANDLING:20 W | DG_FEE:65"
   */
  private parseStandardSurcharges(
    surchargeDetails: string | null,
    params: PriceCalculationParams
  ): SurchargeItem[] {
    if (!surchargeDetails) {
      return [];
    }

    const surcharges: SurchargeItem[] = [];
    const items = surchargeDetails.split('|').map(s => s.trim());

    for (const item of items) {
      const match = item.match(/^([A-Z_]+):(\d+(?:\.\d+)?)\s*([WP%]?)$/);
      if (!match) continue;

      const [, code, amountStr, type] = match;
      let amount = parseFloat(amountStr);
      let surchargeType: 'FIXED' | 'PER_UNIT' | 'PERCENTAGE' = 'FIXED';

      // Calcul selon le type
      if (type === 'W') {
        // Par poids (W = Weight)
        amount = amount * params.weightKG;
        surchargeType = 'PER_UNIT';
      } else if (type === 'P') {
        // Par palette
        amount = amount * params.palletCount;
        surchargeType = 'PER_UNIT';
      } else if (type === '%') {
        // Pourcentage (sera appliqué sur le total)
        surchargeType = 'PERCENTAGE';
      }

      // Certaines surcharges ne s'appliquent que si certaines conditions sont remplies
      if (code === 'DG_FEE' && !params.hasDangerousGoods) {
        continue; // Skip DG fee si pas de marchandises dangereuses
      }

      surcharges.push({
        code,
        description: this.getSurchargeDescription(code),
        amount: Math.round(amount * 100) / 100,
        type: surchargeType,
      });
    }

    return surcharges;
  }

  /**
   * Calcule les surcharges additionnelles basées sur les services demandés
   */
  private calculateAdditionalSurcharges(params: PriceCalculationParams): SurchargeItem[] {
    const surcharges: SurchargeItem[] = [];

    if (params.requiresSpecialHandling) {
      surcharges.push({
        code: 'SPECIAL_HANDLING',
        description: 'Manutention particulière',
        amount: 75,
        type: 'FIXED',
      });
    }

    if (params.requiresTailgate) {
      surcharges.push({
        code: 'TAILGATE',
        description: 'Hayon élévateur',
        amount: 50,
        type: 'FIXED',
      });
    }

    if (params.requiresStraps) {
      surcharges.push({
        code: 'STRAPS',
        description: 'Sangles de sécurité',
        amount: 30,
        type: 'FIXED',
      });
    }

    if (params.requiresThermalCover) {
      surcharges.push({
        code: 'THERMAL_COVER',
        description: 'Couverture thermique',
        amount: 100,
        type: 'FIXED',
      });
    }

    if (params.hasRegulatedProducts) {
      surcharges.push({
        code: 'REGULATED_PRODUCTS',
        description: 'Produits réglementés',
        amount: 80,
        type: 'FIXED',
      });
    }

    if (params.requiresAppointment) {
      surcharges.push({
        code: 'APPOINTMENT',
        description: 'Livraison sur rendez-vous',
        amount: 40,
        type: 'FIXED',
      });
    }

    return surcharges;
  }

  /**
   * Retourne la description d'un code de surcharge standard
   */
  private getSurchargeDescription(code: string): string {
    const descriptions: Record<string, string> = {
      DOC: 'Documentation fee',
      ISPS: 'ISPS Security',
      HANDLING: 'Handling charges',
      SOLAS: 'SOLAS VGM',
      CUSTOMS: 'Customs clearance',
      AMS_ACI: 'AMS/ACI filing',
      DG_FEE: 'Dangerous goods fee',
      BAF: 'Bunker Adjustment Factor',
      CAF: 'Currency Adjustment Factor',
      THC: 'Terminal Handling Charges',
      BL_FEE: 'Bill of Lading fee',
      TELEX_RELEASE: 'Telex release',
      ORIGIN_CHARGES: 'Origin charges',
      DEST_CHARGES: 'Destination charges',
    };

    return descriptions[code] || code.replace(/_/g, ' ');
  }
}
