/* SPDX-License-Identifier: AGPL-3.0-only
   SPDX-FileCopyrightText: 2026 Com'Together */
/* Cœur des tests, PARTAGÉ entre run.html (navigateur) et run-grammar-tests.js (ligne de commande).
   Une seule vérité : contrats + limitations (corpus-grammaire.js) et propriétés (proprietes.js).
   window.runAll() -> résultat structuré. ok = AUCUNE régression ET AUCUNE propriété violée
   (les limitations connues ne bloquent JAMAIS). */
window.runAll = function () {
  const G = window.Grammar, T = window.GRAMMAR_TESTS || {}, out = {};
  if (!G || typeof G.conjugate !== "function") return { error: "grammar.js non chargé (window.Grammar absent)." };

  // 1) CONTRATS linguistiques — un échec = RÉGRESSION.
  const contracts = { total: 0, passed: 0, regressions: [] };
  (T.contracts || []).forEach(c => {
    contracts.total++;
    let got; try { got = G.conjugate(c.v, c.s, c.t); } catch (e) { got = "⚠️ " + e.message; }
    if (got === c.expect) contracts.passed++;
    else contracts.regressions.push({ ...c, got });
  });

  // 2) PROPRIÉTÉS générales.
  const properties = (typeof window.runProperties === "function") ? window.runProperties(G) : { checks: 0, propertiesFailed: 0, failures: [], ok: true };

  // 3) LIMITATIONS connues — jamais comptées comme réussite, jamais bloquantes.
  //    résolue = le moteur produit désormais la cible → à PROMOUVOIR en contrat (notice verte, pas rouge).
  const limitations = (T.limitations || []).map(l => {
    let got; try { got = G.conjugate(l.v, l.s, l.t); } catch (e) { got = "⚠️ " + e.message; }
    const resolved = got === l.expectedEventually;
    const asExpected = got === l.current;
    return { ...l, got, resolved, drifted: !resolved && !asExpected };
  });

  // 4) CHAÎNE DE PHRASE (sentence.js) — teste le message final, pas seulement le verbe.
  const S = window.Sentence, ST = window.SENTENCE_TESTS || {};
  const sentence = { total: 0, passed: 0, regressions: [], limitations: [], available: !!(S && typeof S.build === "function") };
  if (sentence.available) {
    (ST.contracts || []).forEach(c => {
      sentence.total++;
      let got; try { got = S.build(c.tokens, c.ctx || {}); } catch (e) { got = "⚠️ " + e.message; }
      if (got === c.expect) sentence.passed++; else sentence.regressions.push({ ...c, got });
    });
    sentence.limitations = (ST.limitations || []).map(l => {
      let got; try { got = S.build(l.tokens, l.ctx || {}); } catch (e) { got = "⚠️ " + e.message; }
      return { ...l, got, resolved: got === l.expectedEventually, drifted: got !== l.expectedEventually && got !== l.current };
    });
  }

  out.contracts = contracts;
  out.properties = properties;
  out.limitations = limitations;
  out.sentence = sentence;
  out.resolvedCount = limitations.filter(l => l.resolved).length + sentence.limitations.filter(l => l.resolved).length;
  out.driftedCount = limitations.filter(l => l.drifted).length + sentence.limitations.filter(l => l.drifted).length;
  // Blocage de publication : régressions de contrat (verbe OU phrase) OU propriétés violées.
  out.ok = contracts.regressions.length === 0 && properties.ok && sentence.regressions.length === 0;
  return out;
};
