/* =====================================================================
 * Modèle de données d'un bilan SAP + calculs (Glasgow, alertes vitales).
 * ===================================================================== */

function newBilan({ numero, auteur }) {
  const now = new Date().toISOString();
  return {
    id: uid(),
    numero,
    status: 'brouillon',
    createdAt: now,
    updatedAt: now,
    auteurId: auteur ? auteur.id : null,
    auteurNom: auteur ? `${auteur.grade || ''} ${auteur.prenom} ${auteur.nom}`.trim() : '',
    circ: {
      dateHeure: nowLocalInput(),
      numInter: '',
      engin: 'VSAV 1',
      equipage: '',
      adresse: '',
      commune: '',
      motif: '',
      motifDetail: '',
      victime: { nom: '', prenom: '', sexe: '', age: '', naissance: '' },
      securite: '',
      risques: [],
      risquesDetail: '',
      nbVictimes: '1',
      mecanisme: '',
      mecanismeDetail: '',
      environnement: [],
      environnementDetail: '',
      renforts: [],
      renfortsDetail: '',
    },
    vital: {
      x: { hemorragie: '', localisation: '', gestes: [], garrotHeure: '' },
      a: { etat: '', causes: [], risque: '', collier: '' },
      b: { fr: '', spo2: '', qualite: [], o2: '', o2Debit: '', o2Dispositif: '' },
      c: { fc: '', pouls: '', tas: '', tad: '', signes: [], trc: '' },
      d: { avpu: '', gE: '', gV: '', gM: '', pci: '', pciDuree: '', pupilles: [], glycemie: '', glyUnite: 'ml/dL', neuro: [], deficitCote: '' },
      e: { temp: '', echelle: 'EN', douleur: '', douleurLoc: '' },
    },
    lesions: {
      zones: {},
      sample: { s: '', a: '', m: '', p: '', l: '', e: '' },
    },
    gestes: { actes: [], daeChocs: '', autres: '', surveillance: [] },
    transmission: {
      heureAppel: '',
      medecin: '',
      matricule: '',
      avis: '',
      decision: '',
      destination: '',
      service: '',
      heureDepart: '',
      heureArrivee: '',
      observations: '',
    },
  };
}

function nextBilanNumero(bilans) {
  const year = new Date().getFullYear();
  const prefix = `SAP-${year}-`;
  const max = bilans
    .filter((b) => (b.numero || '').startsWith(prefix))
    .reduce((m, b) => Math.max(m, parseInt(b.numero.slice(prefix.length), 10) || 0), 0);
  return prefix + String(max + 1).padStart(4, '0');
}

function bilanVictimeLabel(b) {
  const v = getIn(b, 'circ.victime') || {};
  const nom = [v.prenom, v.nom].filter(Boolean).join(' ');
  const details = [v.sexe, v.age ? `${v.age} ans` : ''].filter(Boolean).join(', ');
  if (!nom && !details) return 'Victime non identifiée';
  return details ? `${nom || 'Victime'} (${details})` : nom;
}

function glasgowScore(d) {
  if (!d || !d.gE || !d.gV || !d.gM) return null;
  return Number(d.gE) + Number(d.gV) + Number(d.gM);
}

/* ---------- Seuils adultes (indicatifs) ---------- */

const VITAL_RANGES = {
  fr: { danger: (v) => v < 10 || v > 30, warning: (v) => v < 12 || v > 20 },
  spo2: { danger: (v) => v < 90, warning: (v) => v < 94 },
  fc: { danger: (v) => v < 40 || v > 150, warning: (v) => v < 50 || v > 120 },
  tas: { danger: (v) => v < 90 || v > 220, warning: (v) => v < 100 || v > 180 },
  tad: { danger: (v) => v > 130, warning: (v) => v > 110 || v < 50 },
  temp: { danger: (v) => v < 32 || v > 41, warning: (v) => v < 35.5 || v > 38.5 },
  glyGL: { danger: (v) => v < 0.5, warning: (v) => v < 0.7 || v > 2.5 },
  douleur: { danger: () => false, warning: (v) => v >= 7 },
};

/** Retourne 'danger' | 'warning' | 'ok' | null pour une constante. */
function vitalTone(key, raw) {
  const v = toNum(raw);
  const range = VITAL_RANGES[key];
  if (v === null || !range) return null;
  if (range.danger(v)) return 'danger';
  if (range.warning(v)) return 'warning';
  return 'ok';
}

function glycemieGL(d) {
  const v = toNum(d && d.glycemie);
  if (v === null) return null;
  const unit = String((d && d.glyUnite) || '').toLowerCase();
  if (unit === 'mmol/l') return v / 5.55;
  if (unit === 'ml/dl' || unit === 'mg/dl') return v / 100;
  return v;
}

/** Liste des alertes détectées à partir du bilan vital. */
function bilanAlerts(b) {
  const v = (b && b.vital) || {};
  const x = v.x || {}, a = v.a || {}, br = v.b || {}, c = v.c || {}, d = v.d || {}, e = v.e || {};
  const alerts = [];
  const push = (level, text) => alerts.push({ level, text });

  if (x.hemorragie === 'oui') push('danger', `Hémorragie externe${x.localisation ? ` (${x.localisation})` : ''}`);
  if ((x.gestes || []).includes('Garrot')) push('danger', `Garrot posé${x.garrotHeure ? ` à ${x.garrotHeure}` : ''}`);

  if (a.etat === 'obstruees') push('danger', 'Voies aériennes obstruées');
  if (a.risque === 'oui') push('warning', 'Risque de non-maintien des VA');

  const fr = vitalTone('fr', br.fr);
  if (fr === 'danger') push('danger', `Détresse respiratoire (FR ${br.fr}/min)`);
  else if (fr === 'warning') push('warning', `FR anormale (${br.fr}/min)`);
  const spo2 = vitalTone('spo2', br.spo2);
  if (spo2 === 'danger') push('danger', `Hypoxie sévère (SpO2 ${br.spo2} %)`);
  else if (spo2 === 'warning') push('warning', `SpO2 basse (${br.spo2} %)`);

  if (c.pouls === 'Absent') push('danger', 'Pouls absent');
  const fc = vitalTone('fc', c.fc);
  if (fc === 'danger') push('danger', `Détresse circulatoire (FC ${c.fc} bpm)`);
  else if (fc === 'warning') push('warning', `FC anormale (${c.fc} bpm)`);
  const tas = vitalTone('tas', c.tas);
  if (tas === 'danger') push('danger', `TA systolique critique (${c.tas} mmHg)`);
  else if (tas === 'warning') push('warning', `TA systolique anormale (${c.tas} mmHg)`);
  if (c.trc === '> 2 s') push('warning', 'TRC allongé (> 2 s)');
  if ((c.signes || []).includes('Marbrures')) push('warning', 'Marbrures');

  const gcs = glasgowScore(d);
  if (gcs !== null && gcs <= 8) push('danger', `Coma (Glasgow ${gcs})`);
  else if (gcs !== null && gcs < 15) push('warning', `Altération de conscience (Glasgow ${gcs})`);
  if (d.avpu === 'U') push('danger', 'Victime inconsciente (AVPU = U)');
  else if (d.avpu === 'P' || d.avpu === 'V') push('warning', `Conscience altérée (AVPU = ${d.avpu})`);
  if (d.pci === 'oui') push('warning', 'Perte de connaissance initiale');
  if ((d.pupilles || []).includes('Anisocores')) push('danger', 'Pupilles anisocores');
  if ((d.neuro || []).some((n) => ['Déficit moteur', 'Asymétrie faciale', 'Trouble de la parole'].includes(n))) {
    push('danger', `Signes neurologiques focaux${d.deficitCote ? ` (${d.deficitCote})` : ''}`);
  }
  const gly = vitalTone('glyGL', glycemieGL(d));
  if (gly === 'danger') push('danger', `Hypoglycémie sévère (${d.glycemie} ${d.glyUnite})`);
  else if (gly === 'warning') push('warning', `Glycémie anormale (${d.glycemie} ${d.glyUnite})`);

  const temp = vitalTone('temp', e.temp);
  if (temp) {
    const t = toNum(e.temp);
    if (temp !== 'ok') push(temp, t < 36 ? `Hypothermie (${e.temp} °C)` : `Hyperthermie (${e.temp} °C)`);
  }
  if (vitalTone('douleur', e.douleur) === 'warning') push('warning', `Douleur intense (${e.echelle} ${e.douleur}/10)`);

  return alerts;
}

/** Niveau global d'un bilan : 'danger' | 'warning' | 'ok'. */
function bilanSeverity(b) {
  const alerts = bilanAlerts(b);
  if (alerts.some((a) => a.level === 'danger')) return 'danger';
  if (alerts.length) return 'warning';
  return 'ok';
}

function bilanZonesTouchees(b) {
  const zones = getIn(b, 'lesions.zones') || {};
  return Object.entries(zones).filter(([, z]) => z && ((z.types || []).length || z.details));
}

const BILAN_STATUS = {
  brouillon: { label: 'Brouillon', tone: 'amber' },
  termine: { label: 'Clôturé', tone: 'emerald' },
};
