/// Résultat d'un itinéraire calculé par Google Maps + Ulys.
class RouteResult {
  /// 'TOLL' ou 'TOLL_FREE'
  final String routeType;
  final int distanceMeters;
  final int durationSeconds;
  final String encodedPolyline;
  final double tollCost;

  const RouteResult({
    required this.routeType,
    required this.distanceMeters,
    required this.durationSeconds,
    required this.encodedPolyline,
    required this.tollCost,
  });

  factory RouteResult.fromMap(Map<String, dynamic> map) {
    return RouteResult(
      routeType: (map['routeType'] ?? 'TOLL').toString(),
      distanceMeters: _parseInt(map['distanceMeters'] ?? 0),
      durationSeconds: _parseInt(map['durationSeconds'] ?? 0),
      encodedPolyline: (map['encodedPolyline'] ?? '').toString(),
      tollCost: _parseDouble(map['tollCost'] ?? 0),
    );
  }

  bool get isTollFree => routeType == 'TOLL_FREE';

  double get distanceKm => distanceMeters / 1000.0;
  double get durationMinutes => durationSeconds / 60.0;
  double get durationHours => durationSeconds / 3600.0;

  /// Calcule le coût carburant.
  /// [consumptionPer100km] : L/100km (ou kWh/100km si électrique)
  /// [fuelPricePerLiter] : €/L ou €/kWh
  /// [freeZoneKm] : km gratuits à déduire (zone de gratuité)
  double fuelCost({
    required double consumptionPer100km,
    required double fuelPricePerLiter,
    double freeZoneKm = 0,
  }) {
    final effectiveKm = (distanceKm - freeZoneKm).clamp(0, double.infinity);
    return (effectiveKm / 100.0) * consumptionPer100km * fuelPricePerLiter;
  }

  /// Calcule le coût de maintenance.
  double maintenanceCost({
    required double costPerKm,
    double freeZoneKm = 0,
  }) {
    final effectiveKm = (distanceKm - freeZoneKm).clamp(0, double.infinity);
    return effectiveKm * costPerKm;
  }

  /// Calcule le coût de main-d'œuvre (techniciens).
  /// [freeZoneMinutes] : minutes gratuites à déduire (zone de gratuité)
  double laborCost({
    required int nbTechnicians,
    required double hourlyRate,
    double freeZoneMinutes = 0,
  }) {
    final effectiveMinutes =
        (durationMinutes - freeZoneMinutes).clamp(0, double.infinity);
    return (effectiveMinutes / 60.0) * nbTechnicians * hourlyRate;
  }

  /// Calcule le coût total pour un aller simple.
  double totalCost({
    required double consumptionPer100km,
    required double fuelPricePerLiter,
    required double maintenanceCostPerKm,
    required int nbTechnicians,
    required double hourlyRate,
    double freeZoneKm = 0,
    double freeZoneMinutes = 0,
  }) {
    return fuelCost(
          consumptionPer100km: consumptionPer100km,
          fuelPricePerLiter: fuelPricePerLiter,
          freeZoneKm: freeZoneKm,
        ) +
        maintenanceCost(
          costPerKm: maintenanceCostPerKm,
          freeZoneKm: freeZoneKm,
        ) +
        laborCost(
          nbTechnicians: nbTechnicians,
          hourlyRate: hourlyRate,
          freeZoneMinutes: freeZoneMinutes,
        ) +
        tollCost;
  }

  static double _parseDouble(dynamic v) {
    if (v is double) return v;
    if (v is int) return v.toDouble();
    if (v is String) return double.tryParse(v) ?? 0.0;
    return 0.0;
  }

  static int _parseInt(dynamic v) {
    if (v is int) return v;
    if (v is double) return v.toInt();
    if (v is String) return int.tryParse(v) ?? 0;
    return 0;
  }
}

/// Prix des carburants (stocké dans Firestore app_config/fuel_prices)
class FuelPrices {
  final double diesel; // €/L
  final double essence; // €/L
  final double electricite; // €/kWh

  const FuelPrices({
    this.diesel = 1.60,
    this.essence = 1.75,
    this.electricite = 0.22,
  });

  factory FuelPrices.fromMap(Map<String, dynamic> map) {
    return FuelPrices(
      diesel: _parseDouble(map['diesel'] ?? 1.60),
      essence: _parseDouble(map['essence'] ?? 1.75),
      electricite: _parseDouble(map['electricite'] ?? 0.22),
    );
  }

  Map<String, dynamic> toMap() => {
        'diesel': diesel,
        'essence': essence,
        'electricite': electricite,
      };

  double priceForFuelType(String fuelType) {
    switch (fuelType.toLowerCase()) {
      case 'diesel':
        return diesel;
      case 'essence':
        return essence;
      case 'electrique':
      case 'électrique':
        return electricite;
      default:
        return diesel;
    }
  }

  static double _parseDouble(dynamic v) {
    if (v is double) return v;
    if (v is int) return v.toDouble();
    if (v is String) return double.tryParse(v) ?? 0.0;
    return 0.0;
  }
}
