/**
 * services/calc.js
 * Helpers partagés : calculs, formatage, seuils métier RLA
 * Champs Baserow table 856 : id_marche, nature{value}, region, observation{value},
 *   taux_phy, taux_fin, avt_phy, avt_fin, m_min, m_max, tot_marche,
 *   date_debut, date_fin, delai_restant, debut_marche, date_fin_marche
 */

const SEUIL_STANDARD      = parseFloat(process.env.SEUIL_STANDARD      || 70);
const SEUIL_MODERNISATION = parseFloat(process.env.SEUIL_MODERNISATION  || 50);
const SEUIL_CRITIQUE_PCT  = parseFloat(process.env.SEUIL_CRITIQUE_PCT   || 90);
const DELAI_CRITIQUE      = parseInt(process.env.DELAI_CRITIQUE         || 45, 10);
const DELAI_ATTENTION     = parseInt(process.env.DELAI_ATTENTION        || 90, 10);

// ─── Helpers Baserow select/multi-select ─────────────────────────────────────

/** Extrait la valeur d'un champ Baserow (select ou string) */
function selectVal(v) {
  if (!v) return '';
  if (typeof v === 'object' && v.value !== undefined) return String(v.value);
  if (Array.isArray(v)) return v.map(x => (x.value !== undefined ? x.value : x)).join(', ');
  return String(v);
}

// ─── Parseurs ────────────────────────────────────────────────────────────────

function parseNum(v) {
  if (v === null || v === undefined || v === '') return 0;
  if (typeof v === 'object') return 0; // objet Baserow non-numérique
  const n = parseFloat(String(v).replace(/\s/g, '').replace(',', '.'));
  return isNaN(n) ? 0 : n;
}

function parseDateFR(d) {
  if (!d) return null;
  const parts = String(d).split(/[\/\-]/);
  if (parts.length === 3) {
    const [a, b, c] = parts;
    if (a.length === 4) return new Date(`${a}-${b}-${c}`);
    if (c.length === 4) return new Date(`${c}-${b}-${a}`);
  }
  const dt = new Date(d);
  return isNaN(dt.getTime()) ? null : dt;
}

// ─── Formatage ───────────────────────────────────────────────────────────────

function formatMontant(v) {
  const n = parseNum(v);
  if (n === 0) return '—';
  return n.toLocaleString('fr-TN', { minimumFractionDigits: 0, maximumFractionDigits: 0 }) + ' DT';
}

function formatDateFR(d) {
  const dt = parseDateFR(d);
  if (!dt) return '—';
  return dt.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric' });
}

function formatPct(v) {
  const n = parseNum(v);
  return n === 0 ? '0 %' : `${n.toFixed(1)} %`;
}

// ─── Statuts métier ───────────────────────────────────────────────────────────

function isCloture(r) {
  const obs = selectVal(r.observation).toLowerCase();
  return obs.includes('clôtur') || obs.includes('clotur') || !!r.date_cloture;
}

function getDelaiRestant(r) {
  // Champ calculé Baserow
  const dField = r.delai_restant;
  if (dField !== null && dField !== undefined && dField !== '') {
    const v = parseInt(String(dField), 10);
    if (!isNaN(v)) return v;
  }
  // Calculer depuis date_fin
  const fin = r.date_fin || r.date_fin_marche || r.datefin;
  const dt  = parseDateFR(fin);
  if (!dt) return null;
  return Math.ceil((dt - new Date()) / 86400000);
}

function niveauAlerte(delai) {
  if (delai === null) return 'indéterminé';
  if (delai <= DELAI_CRITIQUE)  return 'critique';
  if (delai <= DELAI_ATTENTION) return 'attention';
  return 'normal';
}

function niveauAvancement(tauxPhy, nature) {
  const t     = parseNum(tauxPhy);
  const nat   = String(nature || '').toLowerCase();
  const seuil = nat.includes('modern') ? SEUIL_MODERNISATION : SEUIL_STANDARD;
  if (t >= SEUIL_CRITIQUE_PCT) return 'dépassé';
  if (t >= seuil)               return 'sous_avancement';
  return 'normal';
}

/**
 * Résultat financier du marché (pour pilotage proactif)
 * Compare avt_fin (avancement financier en DT) vs m_min / m_max
 */
function resultatFinancier(r) {
  const avt  = parseNum(r.avt_fin);
  const mMin = parseNum(r.m_min);
  const mMax = parseNum(r.m_max ?? r.tot_marche);
  if (avt === 0 && mMin === 0) return 'Non déterminé';
  if (avt > mMax && mMax > 0)  return 'Dépassement';
  if (avt < mMin && mMin > 0)  return 'Sous Min';
  return 'Normal';
}

/**
 * Résultat basé sur l'avancement PHYSIQUE du marché (pilotage proactif)
 * Compare taux_phy vs seuils standards / critique
 */
function resultatPhysique(r) {
  const taux = parseNum(r.taux_phy || r.avt_phy);
  const nat  = String(selectVal(r.nature) || '').toLowerCase();
  const seuil = nat.includes('modern') ? SEUIL_MODERNISATION : SEUIL_STANDARD;
  if (taux === 0) return 'Non déterminé';
  if (taux >= SEUIL_CRITIQUE_PCT) return 'Dépassement';
  if (taux >= seuil)              return 'Normal';
  return 'Sous Avancement';
}

function niveauRisque(r) {
  const delai = getDelaiRestant(r);
  const avt   = parseNum(r.taux_phy || r.avt_phy);
  const nd    = niveauAlerte(delai);
  if (nd === 'critique' || avt >= SEUIL_CRITIQUE_PCT) return 'critique';
  if (nd === 'attention')                              return 'élevé';
  if (avt >= SEUIL_STANDARD)                          return 'moyen';
  return 'faible';
}

// ─── Normalisation d'un marché ───────────────────────────────────────────────

function buildRef(r) {
  const base = r.id_marche || r.reference || String(r.id || '');
  const reg  = r.region_csc || r.region || '';
  return reg ? `${base} - ${reg}` : base;
}

function normalizeMarche(r) {
  const obsValue    = selectVal(r.observation);
  const natureValue = selectVal(r.nature);
  const delaiRestant = getDelaiRestant(r);
  const tauxPhy     = parseNum(r.taux_phy  || r.avt_phy);
  const tauxFin     = parseNum(r.taux_fin  || r.avt_fin);
  const montant     = parseNum(r.tot_marche || r.totmarche || r.montant);
  const mMin        = parseNum(r.m_min);
  const mMax        = parseNum(r.m_max || r.tot_marche);
  const avt_fin_raw = parseNum(r.avt_fin);

  return {
    id:           r.id,
    ref:          buildRef(r),
    projet:       r.projet || '',
    region:       r.region || r.region_csc || '',
    region_csc:   r.region_csc || r.region || '',
    entrepreneur: r.entrepreneur || '',
    nature:       natureValue,
    statut:       obsValue,
    observation:  obsValue,
    lots:         r.lots || '',
    cloture:      isCloture(r),

    date_debut:   formatDateFR(r.date_debut || r.debut_marche),
    date_fin:     formatDateFR(r.date_fin   || r.date_fin_marche),
    date_cloture: formatDateFR(r.date_cloture),
    alerte_echeance: r.Alerte_Echeance || '',

    montant_raw:  montant,
    montant:      formatMontant(montant),
    m_min_raw:    mMin,
    m_min:        formatMontant(mMin),
    m_max_raw:    mMax,
    m_max:        formatMontant(mMax),
    montant_proj_raw: avt_fin_raw,
    montant_proj: formatMontant(avt_fin_raw),

    taux_phy_raw: tauxPhy,
    taux_phy:     formatPct(tauxPhy),
    taux_fin_raw: tauxFin,
    taux_fin:     formatPct(tauxFin),

    delai_restant:     delaiRestant,
    niveau_alerte:     niveauAlerte(delaiRestant),
    niveau_avancement: niveauAvancement(tauxPhy, natureValue),
    niveau_risque:     niveauRisque(r),
    resultat:          resultatFinancier(r),
  };
}

module.exports = {
  SEUIL_STANDARD, SEUIL_MODERNISATION, SEUIL_CRITIQUE_PCT,
  DELAI_CRITIQUE, DELAI_ATTENTION,
  selectVal, parseNum, parseDateFR,
  formatMontant, formatDateFR, formatPct,
  isCloture, getDelaiRestant, niveauAlerte,
  niveauAvancement, resultatFinancier, resultatPhysique, niveauRisque,
  normalizeMarche, buildRef,
};
