import {
  NORMAL_RATE,
  EXEMPTION_TIERS,
  getEligibilityForNaf,
} from "@/data/simulateur/exemption-rules";
import type {
  SimulateurInput,
  SimulateurResult,
  ApplicableTier,
  Confidence,
  ExemptionCode,
  ExemptionTier,
  RatioVARange,
} from "./types";

// ============================================================================
// Moteur de calcul d'exonération — fonction pure, côté client
// ============================================================================

/**
 * Calcule les exonérations applicables pour un profil entreprise donné.
 * Retourne tous les tiers potentiels triés par économies décroissantes.
 */
export function calculateExemption(input: SimulateurInput): SimulateurResult {
  const {
    nafCode,
    annualConsumptionMWh,
    electricityCostEuros,
    valueAddedEuros,
    productionValueEuros,
    hasISO50001,
    isOnCarbonLeakageList,
    installedPowerKW,
    ratioVARange,
  } = input;

  const currentAnnualTax = annualConsumptionMWh * NORMAL_RATE;
  const applicableTiers: ApplicableTier[] = [];

  // Électro-intensité officielle : (tarif de référence × conso) / VA × 100
  // Formule 2040-TIC-VA-E, art. L.312-71 CIBS
  const ratioVA =
    valueAddedEuros && valueAddedEuros > 0
      ? (NORMAL_RATE * annualConsumptionMWh / valueAddedEuros) * 100
      : null;

  // Fourchette effective : déduite du ratio précis OU de la fourchette saisie
  const effectiveRatioRange: RatioVARange | null = ratioVA !== null
    ? rangeFromExactRatio(ratioVA)
    : ratioVARange ?? null;

  // Ratio coût élec / valeur production (pour E26 — L.312-68)
  const electricityCostRatio =
    electricityCostEuros &&
    productionValueEuros &&
    productionValueEuros > 0
      ? (electricityCostEuros / productionValueEuros) * 100
      : null;

  // ── Évaluation des tiers spécifiques au NAF ──────────────────────────────
  const eligibility = getEligibilityForNaf(nafCode);
  const autoQualify = eligibility?.autoQualify ?? false;

  if (eligibility) {
    for (const exemptionCode of eligibility.potentialExemptions) {
      const tier = EXEMPTION_TIERS.find((t) => t.code === exemptionCode);
      if (!tier) continue;

      const evaluation = evaluateTier(
        tier,
        nafCode,
        annualConsumptionMWh,
        ratioVA,
        effectiveRatioRange,
        electricityCostRatio,
        hasISO50001,
        isOnCarbonLeakageList,
        installedPowerKW,
        autoQualify,
      );

      if (evaluation) {
        applicableTiers.push(evaluation);
      }
    }
  }

  // ── Fallback : toujours évaluer les tiers génériques ─────────────────────
  // E23/E24/E25 (électro-intensité seule) + E14b (ultra ≥ 13,5 %) + E26 (coût élec)
  // + E07 (autoconsommation) — s'appliquent quel que soit le NAF
  const existingCodes = new Set(applicableTiers.map((t) => t.tier.code));
  const genericCodes: ExemptionCode[] = [
    "E07",
    "E14b",
    "E23",
    "E24",
    "E25",
    "E26",
  ];

  for (const code of genericCodes) {
    if (existingCodes.has(code)) continue;
    const tier = EXEMPTION_TIERS.find((t) => t.code === code);
    if (!tier) continue;

    const evaluation = evaluateTier(
      tier,
      nafCode,
      annualConsumptionMWh,
      ratioVA,
      effectiveRatioRange,
      electricityCostRatio,
      hasISO50001,
      isOnCarbonLeakageList,
      installedPowerKW,
      false,
    );

    if (evaluation) {
      applicableTiers.push(evaluation);
    }
  }

  // Trier par économies décroissantes (taux le plus bas d'abord)
  applicableTiers.sort((a, b) => a.tier.rate - b.tier.rate);

  const bestTier = applicableTiers[0] ?? null;
  const optimizedAnnualTax = bestTier
    ? annualConsumptionMWh * bestTier.tier.rate
    : currentAnnualTax;
  const annualSavings = currentAnnualTax - optimizedAnnualTax;
  const savingsPercent =
    currentAnnualTax > 0 ? (annualSavings / currentAnnualTax) * 100 : 0;

  // Fourchette d'économies pour le teaser
  const worstApplicable = applicableTiers[applicableTiers.length - 1];
  const savingsRange = {
    min: worstApplicable
      ? currentAnnualTax - annualConsumptionMWh * worstApplicable.tier.rate
      : 0,
    max: annualSavings,
  };

  return {
    isEligible: applicableTiers.length > 0,
    applicableTiers,
    bestTier,
    currentAnnualTax,
    optimizedAnnualTax,
    annualSavings,
    savingsPercent,
    twoYearRetroactiveSavings: annualSavings * 2,
    savingsRange,
  };
}

// ============================================================================
// Évaluation d'un tier pour un profil donné
// ============================================================================

function evaluateTier(
  tier: ExemptionTier,
  nafCode: string,
  consumptionMWh: number,
  ratioVA: number | null,
  ratioRange: RatioVARange | null,
  electricityCostRatio: number | null,
  hasISO50001: boolean,
  isOnCarbonLeakageList: boolean | null,
  installedPowerKW: number | undefined,
  autoQualify?: boolean,
): ApplicableTier | null {
  const missingConditions: string[] = [];
  let confidence: Confidence = "confirmed";

  for (const condition of tier.conditions) {
    switch (condition.type) {
      case "naf_match": {
        const matches = condition.nafPrefixes?.some((p) =>
          nafCode.startsWith(p),
        );
        if (!matches && !autoQualify) return null;
        break;
      }

      case "ratio_va": {
        const threshold = condition.minRatioVA ?? 0;
        if (ratioVA !== null) {
          if (ratioVA < threshold) return null;
        } else if (ratioRange) {
          const rangeMin = RANGE_MIN_MAP[ratioRange];
          if (rangeMin < threshold) return null;
          if (rangeMin === threshold) {
            confidence = downgrade(confidence, "likely");
          }
        } else {
          missingConditions.push(condition.description);
          confidence = downgrade(confidence, "possible");
        }
        break;
      }

      case "electro_intensity": {
        const threshold = condition.minElectroIntensity ?? 0;
        if (ratioVA !== null) {
          if (ratioVA < threshold) return null;
        } else if (ratioRange) {
          const rangeMin = RANGE_MIN_MAP[ratioRange];
          if (rangeMin < threshold) return null;
          if (rangeMin === threshold) {
            confidence = downgrade(confidence, "likely");
          }
        } else {
          missingConditions.push(condition.description);
          confidence = downgrade(confidence, "possible");
        }
        break;
      }

      case "electricity_cost_ratio": {
        const threshold = condition.minElectricityCostRatio ?? 0;
        if (electricityCostRatio !== null) {
          if (electricityCostRatio < threshold) return null;
        } else {
          // Ne pas proposer E26 sans données — condition trop spécifique
          return null;
        }
        break;
      }

      case "consumption_min": {
        const minGWh = condition.minConsumptionGWh ?? 0;
        if (consumptionMWh / 1000 < minGWh) return null;
        break;
      }

      case "iso_50001": {
        if (!hasISO50001) {
          missingConditions.push(condition.description);
          confidence = downgrade(confidence, "possible");
        }
        break;
      }

      case "carbon_leakage": {
        if (isOnCarbonLeakageList === false) return null;
        if (isOnCarbonLeakageList === null) {
          missingConditions.push(condition.description);
          confidence = downgrade(confidence, "likely");
        }
        break;
      }

      case "power_threshold": {
        if (installedPowerKW !== undefined) {
          if (
            condition.maxPowerKW !== undefined &&
            installedPowerKW > condition.maxPowerKW
          )
            return null;
        } else {
          missingConditions.push(condition.description);
          confidence = downgrade(confidence, "possible");
        }
        break;
      }
    }
  }

  return { tier, confidence, missingConditions };
}

// ============================================================================
// Helpers
// ============================================================================

/** Bornes basses des fourchettes officielles d'électro-intensité (%) */
const RANGE_MIN_MAP: Record<RatioVARange, number> = {
  "<0.5%": 0,
  "0.5-2.25%": 0.5,
  "2.25-3.375%": 2.25,
  "3.375-6.75%": 3.375,
  "6.75-13.5%": 6.75,
  ">13.5%": 13.5,
};

/** Convertit un ratio précis (%) en fourchette officielle */
function rangeFromExactRatio(ratio: number): RatioVARange {
  if (ratio >= 13.5) return ">13.5%";
  if (ratio >= 6.75) return "6.75-13.5%";
  if (ratio >= 3.375) return "3.375-6.75%";
  if (ratio >= 2.25) return "2.25-3.375%";
  if (ratio >= 0.5) return "0.5-2.25%";
  return "<0.5%";
}

const CONFIDENCE_ORDER: Confidence[] = ["confirmed", "likely", "possible"];

function downgrade(current: Confidence, to: Confidence): Confidence {
  const currentIdx = CONFIDENCE_ORDER.indexOf(current);
  const toIdx = CONFIDENCE_ORDER.indexOf(to);
  return toIdx > currentIdx ? to : current;
}

/**
 * Formate un montant en euros (ex: 72900 → "72 900 €")
 */
export function formatEuros(amount: number): string {
  return new Intl.NumberFormat("fr-FR", {
    style: "currency",
    currency: "EUR",
    maximumFractionDigits: 0,
  }).format(amount);
}
