document.addEventListener("DOMContentLoaded", () => {
  const transportMode = document.getElementById("transportMode");
  const containerField = document.getElementById("containerField");
  const volumeField = document.getElementById("volumeField");
  const finalDeliveryCheck = document.getElementById("finalDeliveryCheck");
  const cityField = document.getElementById("cityField");
  const form = document.getElementById("importForm");
  const resultSection = document.getElementById("resultSection");
  const resultContent = document.getElementById("resultContent");
  const resetBtn = document.getElementById("resetBtn");
  const exchangeRateInput = document.getElementById("exchangeRate");
  const rateInfo = document.getElementById("rateInfo");

  const portChinaSelect = document.getElementById("portChina");
  const portEuropeSelect = document.getElementById("portEurope");

  const fret20Input = document.getElementById("fret20");
  const fret40Input = document.getElementById("fret40");
  const fret40hqInput = document.getElementById("fret40hq");
  const fretM3Input = document.getElementById("fretM3");
  const fobFeeInput = document.getElementById("fobFee");
  const customsClearanceInput = document.getElementById("customsClearance");
  const storageFeeInput = document.getElementById("storageFee");

  const ROUTE_UPDATED_AT = "2026-04-09";

  const europeBaseRates = {
    "Marseille Fos": {
      container20: 2500,
      container40: 3200,
      container40hq: 4500,
      lclPerM3: 50,
      customsClearance: 300,
      storageFee: 200
    },
    "Le Havre": {
      container20: 2550,
      container40: 3300,
      container40hq: 4600,
      lclPerM3: 52,
      customsClearance: 310,
      storageFee: 210
    },
    "Rotterdam": {
      container20: 2450,
      container40: 3150,
      container40hq: 4400,
      lclPerM3: 49,
      customsClearance: 320,
      storageFee: 220
    },
    "Anvers": {
      container20: 2480,
      container40: 3180,
      container40hq: 4450,
      lclPerM3: 50,
      customsClearance: 320,
      storageFee: 220
    },
    "Hambourg": {
      container20: 2520,
      container40: 3250,
      container40hq: 4520,
      lclPerM3: 52,
      customsClearance: 320,
      storageFee: 225
    },
    "Gênes": {
      container20: 2580,
      container40: 3320,
      container40hq: 4650,
      lclPerM3: 54,
      customsClearance: 315,
      storageFee: 215
    },
    "Valence": {
      container20: 2560,
      container40: 3290,
      container40hq: 4620,
      lclPerM3: 53,
      customsClearance: 315,
      storageFee: 212
    }
  };

  const chinaPortAdjustments = {
    "Shanghai": {
      container20: 0,
      container40: 0,
      container40hq: 0,
      lclPerM3: 0,
      originFee: 150
    },
    "Shenzhen": {
      container20: 20,
      container40: 50,
      container40hq: 50,
      lclPerM3: 2,
      originFee: 155
    },
    "Ningbo": {
      container20: -20,
      container40: -20,
      container40hq: -50,
      lclPerM3: 0,
      originFee: 150
    },
    "Qingdao": {
      container20: -50,
      container40: -50,
      container40hq: -50,
      lclPerM3: -1,
      originFee: 145
    },
    "Xiamen": {
      container20: 10,
      container40: 30,
      container40hq: 20,
      lclPerM3: 2,
      originFee: 155
    },
    "Tianjin": {
      container20: 40,
      container40: 40,
      container40hq: 60,
      lclPerM3: 1,
      originFee: 160
    },
    "Guangzhou": {
      container20: 30,
      container40: 40,
      container40hq: 40,
      lclPerM3: 1,
      originFee: 162
    },
    "Dalian": {
      container20: -40,
      container40: -30,
      container40hq: -10,
      lclPerM3: 0,
      originFee: 150
    }
  };

  const freightRates = Object.entries(chinaPortAdjustments).flatMap(([from, chinaAdj]) =>
    Object.entries(europeBaseRates).map(([to, euBase]) => ({
      from,
      to,
      container20: euBase.container20 + chinaAdj.container20,
      container40: euBase.container40 + chinaAdj.container40,
      container40hq: euBase.container40hq + chinaAdj.container40hq,
      lclPerM3: euBase.lclPerM3 + chinaAdj.lclPerM3,
      originFee: chinaAdj.originFee,
      customsClearance: euBase.customsClearance,
      storageFee: euBase.storageFee,
      updatedAt: ROUTE_UPDATED_AT
    }))
  );

  let liveRateMeta = {
    source: "",
    date: "",
    loaded: false
  };

  function toggle(el, show) {
    if (!el) return;
    el.classList.toggle("hidden", !show);
  }

  function updateTransportVisibility() {
    const isContainer = transportMode?.value === "container";
    toggle(containerField, isContainer);
    toggle(volumeField, !isContainer);
  }

  function updateDeliveryVisibility() {
    toggle(cityField, !!finalDeliveryCheck?.checked);
  }

  function getNumber(id) {
    return parseFloat(document.getElementById(id)?.value) || 0;
  }

  function getText(id) {
    return (document.getElementById(id)?.value || "").trim();
  }

  function formatCurrency(value, currency) {
    return new Intl.NumberFormat("fr-FR", {
      style: "currency",
      currency
    }).format(Number(value) || 0);
  }

  function formatDateTimeText(raw) {
    if (!raw) return "-";
    const d = new Date(raw);
    if (Number.isNaN(d.getTime())) return raw;
    return d.toLocaleString("fr-FR");
  }

  function escapeHtml(value) {
    return String(value)
      .replaceAll("&", "&amp;")
      .replaceAll("<", "&lt;")
      .replaceAll(">", "&gt;")
      .replaceAll('"', "&quot;")
      .replaceAll("'", "&#039;");
  }

  function convertToEUR(value, currency, usdToEurRate) {
    return currency === "USD" ? value * usdToEurRate : value;
  }

  function convertFromEUR(value, targetCurrency, usdToEurRate) {
    if (targetCurrency === "USD") {
      if (!usdToEurRate) return 0;
      return value / usdToEurRate;
    }
    return value;
  }

  function line(label, value, strong = false) {
    return `
      <div class="line">
        <span>${escapeHtml(label)}</span>
        <span>${strong ? `<strong>${value}</strong>` : value}</span>
      </div>
    `;
  }

  function dualLine(label, valueEUR, showUSD, usdToEurRate, strong = false) {
    if (!showUSD) {
      return line(label, formatCurrency(valueEUR, "EUR"), strong);
    }

    const valueUSD = convertFromEUR(valueEUR, "USD", usdToEurRate);

    return `
      ${line(label, formatCurrency(valueEUR, "EUR"), strong)}
      ${line(`${label} ($)`, formatCurrency(valueUSD, "USD"), strong)}
    `;
  }

  function setRateInfo(message, isError = false) {
    if (!rateInfo) return;
    rateInfo.textContent = message;
    rateInfo.style.color = isError ? "#b95b5b" : "#627a50";
  }

  function findRouteRate(from, to) {
    return freightRates.find(route => route.from === from && route.to === to) || null;
  }

  function applyRouteRates() {
    const from = portChinaSelect?.value || "";
    const to = portEuropeSelect?.value || "";

    const route = findRouteRate(from, to);

    if (!route) {
      console.warn(`Aucun tarif interne trouvé pour ${from} -> ${to}`);
      return;
    }

    if (fret20Input) fret20Input.value = route.container20 ?? 0;
    if (fret40Input) fret40Input.value = route.container40 ?? 0;
    if (fret40hqInput) fret40hqInput.value = route.container40hq ?? 0;
    if (fretM3Input) fretM3Input.value = route.lclPerM3 ?? 0;
    if (fobFeeInput) fobFeeInput.value = route.originFee ?? 0;
    if (customsClearanceInput) customsClearanceInput.value = route.customsClearance ?? 0;
    if (storageFeeInput) storageFeeInput.value = route.storageFee ?? 0;

    console.log(`Tarifs internes appliqués pour ${from} -> ${to} (${route.updatedAt})`);
  }

  async function fetchWithTimeout(url, options = {}, timeoutMs = 6000) {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), timeoutMs);

    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal,
        cache: "no-store"
      });
      return response;
    } finally {
      clearTimeout(timeout);
    }
  }

  async function updateExchangeRate() {
    if (!exchangeRateInput) return;

    try {
      setRateInfo("Chargement du taux automatique...");

      const response = await fetchWithTimeout("https://open.er-api.com/v6/latest/USD");

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }

      const data = await response.json();

      if (data?.result !== "success") {
        throw new Error("Réponse API non valide.");
      }

      const usdToEur = Number(data?.rates?.EUR);
      const updateDate = data?.time_last_update_utc || "";

      if (!usdToEur || Number.isNaN(usdToEur)) {
        throw new Error("Taux USD → EUR introuvable.");
      }

      exchangeRateInput.value = usdToEur.toFixed(4);

      liveRateMeta = {
        source: "open.er-api",
        date: updateDate,
        loaded: true
      };

      setRateInfo(
        updateDate
          ? `Taux automatique chargé via open.er-api (${updateDate})`
          : "Taux automatique chargé via open.er-api"
      );
    } catch (error) {
      console.error("Erreur lors de la récupération du taux :", error);

      liveRateMeta = {
        source: "",
        date: "",
        loaded: false
      };

      setRateInfo("Impossible de charger le taux automatique. Valeur manuelle conservée.", true);
    }
  }

  function validate(data) {
    if (!data.identifiant) {
      alert("Veuillez renseigner un identifiant.");
      return false;
    }

    if (!data.incoterm) {
      alert("Veuillez choisir un Incoterm.");
      return false;
    }

    if (data.quantity <= 0) {
      alert("Quantité invalide.");
      return false;
    }

    if (data.unitPrice <= 0) {
      alert("Prix unitaire invalide.");
      return false;
    }

    if (data.currency === "USD" && data.rate <= 0) {
      alert("Taux USD → EUR invalide.");
      return false;
    }

    if (data.transportMode === "volume" && data.volume <= 0) {
      alert("Volume invalide.");
      return false;
    }

    if (data.customsRate < 0) {
      alert("Le taux de douane ne peut pas être négatif.");
      return false;
    }

    if (data.vatRate < 0) {
      alert("Le taux de TVA ne peut pas être négatif.");
      return false;
    }

    if (data.insuranceRate < 0) {
      alert("Le taux d'assurance ne peut pas être négatif.");
      return false;
    }

    return true;
  }

  function collectData() {
    const currency = getText("devise") === "usd" ? "USD" : "EUR";

    return {
      identifiant: getText("identifiant"),
      prenom: getText("prenom"),
      nom: getText("nom"),
      email: getText("email"),
      telephone: getText("telephone"),
      adresse: getText("adresse"),
      ville: getText("ville"),
      pays: getText("pays"),
      produit: getText("productName"),
      incoterm: getText("incoterm"),
      hsCode: getText("hsCode"),
      portChina: getText("portChina"),
      portEurope: getText("portEurope"),
      transportMode: getText("transportMode"),
      container: getText("container"),
      volume: getNumber("volumeBlock"),
      quantity: Math.floor(getNumber("quantity")),
      unitPrice: getNumber("exw"),
      currency,
      rate: getNumber("exchangeRate"),
      customsRate: getNumber("customsRate") / 100,
      vatRate: getNumber("vatRate") / 100,
      vatEnabled: getText("vatPaid") === "oui",
      insuranceRate: getNumber("insuranceRate") / 100,
      originFee: getNumber("fobFee"),
      clearance: getNumber("customsClearance"),
      storage: getNumber("storageFee"),
      freight20: getNumber("fret20"),
      freight40: getNumber("fret40"),
      freight40hq: getNumber("fret40hq"),
      freightM3: getNumber("fretM3"),
      deliveryEnabled: !!finalDeliveryCheck?.checked,
      deliveryCity: getText("deliveryCity"),
      deliveryFee: finalDeliveryCheck?.checked ? getNumber("finalDeliveryFee") : 0,
      liveRateSource: liveRateMeta.source,
      liveRateDate: liveRateMeta.date,
      liveRateLoaded: liveRateMeta.loaded
    };
  }

  function calculate(data) {
    const unitPriceEUR = convertToEUR(data.unitPrice, data.currency, data.rate);
    const goodsValueEUR = unitPriceEUR * data.quantity;

    let theoreticalFreight = 0;

    if (data.transportMode === "container") {
      if (data.container === "20") theoreticalFreight = data.freight20;
      if (data.container === "40") theoreticalFreight = data.freight40;
      if (data.container === "40HQ") theoreticalFreight = data.freight40hq;
    } else {
      theoreticalFreight = data.volume * data.freightM3;
    }

    let includedOrigin = false;
    let includedFreight = false;
    let includedInsurance = false;
    let includedClearance = false;
    let includedStorage = false;
    let includedDelivery = false;
    let includedCustoms = false;
    let includedVAT = false;

    switch (data.incoterm) {
      case "EXW":
        break;
      case "FOB":
        includedOrigin = true;
        break;
      case "CIF":
        includedOrigin = true;
        includedFreight = true;
        includedInsurance = true;
        break;
      case "DAP":
        includedOrigin = true;
        includedFreight = true;
        includedInsurance = true;
        includedClearance = true;
        includedStorage = true;
        includedDelivery = true;
        break;
      case "DDP":
        includedOrigin = true;
        includedFreight = true;
        includedInsurance = true;
        includedClearance = true;
        includedStorage = true;
        includedDelivery = true;
        includedCustoms = true;
        includedVAT = true;
        break;
      default:
        break;
    }

    const originCost = includedOrigin ? 0 : data.originFee;
    const freightCost = includedFreight ? 0 : theoreticalFreight;

    const insuranceBase = goodsValueEUR + originCost + freightCost;
    const insuranceCost = includedInsurance ? 0 : insuranceBase * data.insuranceRate;

    const customsBase = goodsValueEUR + originCost + freightCost + insuranceCost;
    const customs = includedCustoms ? 0 : customsBase * data.customsRate;

    const clearanceCost = includedClearance ? 0 : data.clearance;
    const storageCost = includedStorage ? 0 : data.storage;
    const deliveryCost = includedDelivery ? 0 : data.deliveryFee;

    const vatBase = customsBase + customs + clearanceCost + storageCost + deliveryCost;
    const vat = data.vatEnabled && !includedVAT ? vatBase * data.vatRate : 0;

    const total =
      goodsValueEUR +
      originCost +
      freightCost +
      insuranceCost +
      customs +
      clearanceCost +
      storageCost +
      deliveryCost +
      vat;

    return {
      unitPriceEUR,
      goodsValueEUR,
      theoreticalFreight,
      originCost,
      freightCost,
      insuranceCost,
      customsBase,
      customs,
      clearanceCost,
      storageCost,
      deliveryCost,
      vatBase,
      vat,
      total,
      unit: total / data.quantity,
      includedOrigin,
      includedFreight,
      includedInsurance,
      includedClearance,
      includedStorage,
      includedDelivery,
      includedCustoms,
      includedVAT
    };
  }

  function getContainerLabel(data) {
    if (data.transportMode !== "container") {
      return `${data.volume} m³`;
    }

    if (data.container === "20") return "20 pieds";
    if (data.container === "40") return "40 pieds";
    return "40 pieds HQ";
  }

  function getLiveStatusLabel(data) {
    return data.liveRateLoaded ? "Oui" : "Non";
  }

  function getRateSourceLabel(data) {
    if (!data.liveRateLoaded) return "Aucune";
    const dateText = data.liveRateDate ? ` (${formatDateTimeText(data.liveRateDate)})` : "";
    return `${data.liveRateSource}${dateText}`;
  }

  function getIncotermMeaning(incoterm) {
    if (incoterm === "EXW") return "Départ usine";
    if (incoterm === "FOB") return "Franco bord";
    if (incoterm === "CIF") return "Coût, assurance, fret inclus";
    if (incoterm === "DAP") return "Rendu au lieu de destination";
    if (incoterm === "DDP") return "Rendu droits acquittés";
    return "-";
  }

  function render(data, r) {
    const now = new Date();
    const dateLocale = now.toLocaleDateString("fr-FR");
    const timeLocale = now.toLocaleTimeString("fr-FR");
    const showUSD = data.currency === "USD";
    const customerName = [data.prenom, data.nom].filter(Boolean).join(" ").trim();
    const addressBlock = [data.adresse, data.ville, data.pays].filter(Boolean).join(", ").trim();
    const containerLabel = getContainerLabel(data);

    const includedItems = [];
    if (r.includedOrigin) includedItems.push("frais origine");
    if (r.includedFreight) includedItems.push("fret principal");
    if (r.includedInsurance) includedItems.push("assurance");
    if (r.includedCustoms) includedItems.push("droits de douane");
    if (r.includedClearance) includedItems.push("dédouanement");
    if (r.includedStorage) includedItems.push("frais portuaires");
    if (r.includedDelivery) includedItems.push("livraison finale");
    if (r.includedVAT) includedItems.push("TVA");

    const addedLines = [];

    if (r.originCost > 0) {
      addedLines.push(dualLine("Frais origine ajoutés", r.originCost, showUSD, data.rate));
    }

    if (r.freightCost > 0) {
      addedLines.push(dualLine("Fret ajouté", r.freightCost, showUSD, data.rate));
    }

    if (r.insuranceCost > 0) {
      addedLines.push(dualLine("Assurance ajoutée", r.insuranceCost, showUSD, data.rate));
    }

    if (r.customs > 0) {
      addedLines.push(dualLine("Droits de douane", r.customs, showUSD, data.rate));
    }

    if (r.clearanceCost > 0) {
      addedLines.push(dualLine("Dédouanement", r.clearanceCost, showUSD, data.rate));
    }

    if (r.storageCost > 0) {
      addedLines.push(dualLine("Frais portuaires", r.storageCost, showUSD, data.rate));
    }

    if (r.deliveryCost > 0) {
      addedLines.push(dualLine("Livraison finale", r.deliveryCost, showUSD, data.rate));
    }

    if (r.vat > 0) {
      addedLines.push(dualLine("TVA", r.vat, showUSD, data.rate));
    }

    const addedCostsHtml = addedLines.length
      ? addedLines.join("")
      : `<div class="empty-state">Aucun coût supplémentaire ajouté par le simulateur pour cet incoterm.</div>`;

    const includedText = includedItems.length
      ? includedItems.join(", ")
      : "aucun poste logistique ou fiscal particulier";

    return `
      <div class="result-top clean-result-top">
        <div>
          <h2 class="result-title">Simulation ${escapeHtml(data.identifiant)}</h2>
          <div class="result-meta">
            Établie le ${dateLocale} à ${timeLocale}<br>
            ${customerName ? `${escapeHtml(customerName)}<br>` : ""}
            ${addressBlock ? `${escapeHtml(addressBlock)}<br>` : ""}
            ${data.email ? escapeHtml(data.email) : ""}
            ${data.email && data.telephone ? " | " : ""}
            ${data.telephone ? escapeHtml(data.telephone) : ""}
          </div>
        </div>

        <div class="actions result-actions">
          <button type="button" class="btn-primary" id="printBtn">Imprimer</button>
          <button type="button" class="btn-danger" id="clearBtn">Effacer le résultat</button>
        </div>
      </div>

      <div class="results-master-grid">
        <div class="hero-card">
          <div class="hero-label">Incoterm</div>
          <div class="hero-value">${escapeHtml(data.incoterm || "-")}</div>
          <div class="hero-sub">${escapeHtml(getIncotermMeaning(data.incoterm))}</div>
        </div>

        <div class="hero-card">
          <div class="hero-label">Prix unitaire fournisseur</div>
          <div class="hero-value">${formatCurrency(r.unitPriceEUR, "EUR")}</div>
          <div class="hero-sub">${showUSD ? formatCurrency(data.unitPrice, "USD") : "Base saisie en euro"}</div>
        </div>

        <div class="hero-card">
          <div class="hero-label">Total rendu</div>
          <div class="hero-value">${formatCurrency(r.total, "EUR")}</div>
          <div class="hero-sub">${showUSD ? formatCurrency(convertFromEUR(r.total, "USD", data.rate), "USD") : "Montant estimatif final"}</div>
        </div>

        <div class="hero-card">
          <div class="hero-label">Coût rendu par unité</div>
          <div class="hero-value">${formatCurrency(r.unit, "EUR")}</div>
          <div class="hero-sub">${showUSD ? formatCurrency(convertFromEUR(r.unit, "USD", data.rate), "USD") : "Par unité importée"}</div>
        </div>

        <div class="card">
          <h3>Résumé financier</h3>
          ${dualLine("Valeur marchandise", r.goodsValueEUR, showUSD, data.rate)}
          ${dualLine("Coûts ajoutés par le simulateur", r.total - r.goodsValueEUR, showUSD, data.rate)}
          <div class="separator"></div>
          ${dualLine("Total rendu estimé", r.total, showUSD, data.rate, true)}
          ${dualLine("Coût rendu unitaire", r.unit, showUSD, data.rate, true)}
        </div>

        <div class="card">
          <h3>Coûts ajoutés</h3>
          ${addedCostsHtml}
        </div>

        <div class="card">
          <h3>Lecture de l’incoterm</h3>
          <div class="info-note">
            Pour l’incoterm <strong>${escapeHtml(data.incoterm)}</strong>, le simulateur considère que le prix saisi inclut déjà : ${escapeHtml(includedText)}.
          </div>

          <div class="mini-lines">
            ${line("Produit", escapeHtml(data.produit || "-"))}
            ${line("Code HS", escapeHtml(data.hsCode || "-"))}
            ${line("Quantité", escapeHtml(String(data.quantity)))}
            ${line("Transport", escapeHtml(data.transportMode === "container" ? "Conteneur" : "Groupage"))}
            ${line("Type / Volume", escapeHtml(containerLabel))}
            ${line("Port de départ", escapeHtml(data.portChina || "-"))}
            ${line("Port d’arrivée", escapeHtml(data.portEurope || "-"))}
            ${line("Douane", `${(data.customsRate * 100).toFixed(2)} %`)}
            ${line("TVA", data.vatEnabled ? `Oui (${(data.vatRate * 100).toFixed(2)} %)` : "Non")}
            ${line("Taux USD → EUR", data.rate ? data.rate.toFixed(4) : "-")}
            ${line("Livraison finale", data.deliveryEnabled ? escapeHtml(data.deliveryCity || "Oui") : "Non")}
          </div>
        </div>

        <div class="card">
          <h3>Base de calcul</h3>
          ${line("Base douane", formatCurrency(r.customsBase, "EUR"))}
          ${line("Base TVA", formatCurrency(r.vatBase, "EUR"))}
          ${line("Assurance", `${(data.insuranceRate * 100).toFixed(2)} %`)}
          ${line("Taux automatique chargé", getLiveStatusLabel(data))}
          ${line("Source du taux", escapeHtml(getRateSourceLabel(data)))}
          ${line("Fret théorique", formatCurrency(r.theoreticalFreight, "EUR"))}
        </div>
      </div>

      <div class="info-box clean-info-box">
        Estimation simplifiée. Le prix saisi est interprété comme un prix correspondant à l’incoterm choisi. Le simulateur n’ajoute que les postes non inclus dans cet incoterm.
      </div>
    `;
  }

  if (form) {
    form.addEventListener("submit", (e) => {
      e.preventDefault();

      const data = collectData();
      if (!validate(data)) return;

      const result = calculate(data);
      resultContent.innerHTML = render(data, result);
      resultSection.style.display = "block";
      resultSection.scrollIntoView({ behavior: "smooth", block: "start" });
    });
  }

  document.addEventListener("click", (event) => {
    if (event.target && event.target.id === "printBtn") {
      window.print();
    }

    if (event.target && event.target.id === "clearBtn") {
      resultContent.innerHTML = "";
      resultSection.style.display = "none";
    }
  });

  if (resetBtn) {
    resetBtn.addEventListener("click", () => {
      setTimeout(() => {
        updateTransportVisibility();
        updateDeliveryVisibility();
        resultContent.innerHTML = "";
        resultSection.style.display = "none";
        applyRouteRates();
      }, 0);
    });
  }

  if (transportMode) {
    transportMode.addEventListener("change", updateTransportVisibility);
  }

  if (finalDeliveryCheck) {
    finalDeliveryCheck.addEventListener("change", updateDeliveryVisibility);
  }

  if (portChinaSelect) {
    portChinaSelect.addEventListener("change", applyRouteRates);
  }

  if (portEuropeSelect) {
    portEuropeSelect.addEventListener("change", applyRouteRates);
  }

  updateTransportVisibility();
  updateDeliveryVisibility();
  applyRouteRates();
  updateExchangeRate();
});