"""Critères d'acceptation du cahier des charges (§7 et §8.7).

Ces tests exécutent le seed complet sur le corpus réel, puis vérifient en base
les sept garde-fous du §7 et les scénarios de démonstration du §8.7. Ils
échouent si une régression altère un fait — c'est leur seule raison d'être.
"""

from __future__ import annotations

import json
import sqlite3

import pytest

from pipeline import db
from pipeline.seed_from_research import ensemencer


@pytest.fixture(scope="module")
def base_complete(tmp_path_factory) -> sqlite3.Connection:
    """Base issue d'un seed complet du corpus, partagée par le module."""
    chemin = tmp_path_factory.mktemp("acceptation") / "veille.db"
    cx = db.initialiser(chemin)
    ensemencer(cx)
    return cx


def _texte(cx: sqlite3.Connection, identifiant: str) -> sqlite3.Row:
    ligne = cx.execute("SELECT * FROM v_textes WHERE id = ?", (identifiant,)).fetchone()
    assert ligne is not None, f"{identifiant} absent de la base"
    return ligne


def _affaires(cx: sqlite3.Connection, identifiant: str) -> list[str]:
    return [
        r["numero_affaire"]
        for r in cx.execute(
            "SELECT numero_affaire FROM decisions_cc WHERE texte_id = ? ORDER BY numero_affaire",
            (identifiant,),
        )
    ]


# ─────────────────────────────────────────────────────────────────────────────
# §2 — volumétrie
# ─────────────────────────────────────────────────────────────────────────────


def test_au_moins_49_textes(base_complete) -> None:
    total = base_complete.execute("SELECT COUNT(*) FROM textes").fetchone()[0]
    assert total >= 49


def test_chaque_texte_a_au_moins_une_source_url(base_complete) -> None:
    """§8.2 : 100 % des entrées avec au moins une source URL."""
    orphelins = [
        r["id"]
        for r in base_complete.execute(
            "SELECT id FROM textes t "
            "WHERE NOT EXISTS (SELECT 1 FROM sources s WHERE s.texte_id = t.id)"
        )
    ]
    assert orphelins == []


def test_toutes_les_sources_ont_une_url_absolue(base_complete) -> None:
    mauvaises = [
        r["url"]
        for r in base_complete.execute(
            "SELECT url FROM sources WHERE url NOT LIKE 'http://%' AND url NOT LIKE 'https://%'"
        )
    ]
    assert mauvaises == []


# ─────────────────────────────────────────────────────────────────────────────
# §7 — les sept garde-fous
# ─────────────────────────────────────────────────────────────────────────────


def test_1_chlordecone(base_complete) -> None:
    texte = _texte(base_complete, "loi-2026-491")
    assert texte["numero_officiel"] == "2026-491"
    assert texte["statut"] == "promulguee"
    assert texte["date_promulgation"] == "2026-06-12"
    assert texte["guadeloupe_pertinence"] == "forte"
    assert {"sante", "outre_mer", "memoire_patrimoine"} <= set(json.loads(texte["themes"]))
    assert texte["nb_sources"] > 0


def test_2_fraudes_sociales_et_fiscales(base_complete) -> None:
    texte = _texte(base_complete, "loi-2026-534")
    assert texte["statut"] == "promulguee"
    assert texte["date_promulgation"] == "2026-06-25"
    assert _affaires(base_complete, "loi-2026-534") == ["2026-904 DC"]


def test_3_loi_riposte(base_complete) -> None:
    """Statut, événement de saisine, et amende forfaitaire à 500 € — pas 1 500 €."""
    texte = _texte(base_complete, "loi-riposte")
    assert texte["statut"] == "adoptee_non_promulguee"
    assert texte["numero_officiel"] is None

    saisines = base_complete.execute(
        "SELECT date_evenement, description FROM evenements "
        "WHERE texte_id = 'loi-riposte' AND type_etape = 'saisine_cc'"
    ).fetchall()
    assert len(saisines) == 1
    assert saisines[0]["date_evenement"] == "2026-07-24"
    assert "2026-915 DC" in saisines[0]["description"]
    assert "24 juillet 2026" in saisines[0]["description"]

    points = json.loads(texte["points_cles"])
    assert any("500 €" in p for p in points), "l'AFD à 500 € doit figurer aux points clés"
    # Le montant abandonné ne doit apparaître que présenté comme tel.
    for point in points:
        if "1 500 €" in point:
            assert "abandonn" in point or "Sénat 1" in point


def test_4_ppl_aide_a_mourir(base_complete) -> None:
    texte = _texte(base_complete, "ppl-aide-a-mourir")
    assert texte["date_adoption"] == "2026-07-15"
    assert _affaires(base_complete, "ppl-aide-a-mourir") == ["2026-910 DC"]
    assert "291" in (texte["resume"] or ""), "le vote 291/241 doit apparaître au résumé"


def test_5_pjl_pacte_migration(base_complete) -> None:
    texte = _texte(base_complete, "pjl-pacte-migration")
    assert texte["statut"] == "navette"
    assert "migration" in json.loads(texte["themes"])


def test_6_simplification_vie_economique(base_complete) -> None:
    texte = _texte(base_complete, "loi-2026-403")
    assert texte["statut"] == "promulguee"

    decision = base_complete.execute(
        "SELECT * FROM decisions_cc WHERE texte_id = 'loi-2026-403'"
    ).fetchone()
    assert decision["numero_affaire"] == "2026-903 DC"
    assert decision["resultat"] == "non_conformite_partielle"
    assert "25 articles" in decision["resume"]

    note = (texte["guadeloupe_note"] or "").lower()
    assert "march" in note and "ultramarin" in note


def test_7_senatoriales_la_guadeloupe_n_est_pas_concernee(base_complete) -> None:
    """Le point 4 de la validation de phase 5 tranche : série 1, renouvelée en 2023."""
    echeance = base_complete.execute(
        "SELECT * FROM echeances WHERE code = 'senatoriales-2026'"
    ).fetchone()
    assert echeance is not None
    assert echeance["date_echeance"] == "2026-09-27"
    assert echeance["concerne_guadeloupe"] == 0
    assert "n'est PAS concernée" in echeance["note_guadeloupe"]
    assert "série 1" in echeance["note_guadeloupe"]


# ─────────────────────────────────────────────────────────────────────────────
# §8.7 — scénarios de démonstration
# ─────────────────────────────────────────────────────────────────────────────


def test_recherche_chlordecone_classe_la_bonne_loi_en_tete(base_complete) -> None:
    lignes = base_complete.execute(
        """
        SELECT t.id
          FROM textes_fts f
          JOIN textes t ON t.rowid = f.rowid
         WHERE textes_fts MATCH 'chlordecone'
         ORDER BY bm25(textes_fts, 10.0, 5.0, 3.0, 2.0, 2.0, 1.0)
        """
    ).fetchall()
    assert lignes, "la recherche « chlordécone » ne doit pas être vide"
    assert lignes[0]["id"] == "loi-2026-491"


def test_facette_devant_le_conseil_constitutionnel(base_complete) -> None:
    total = base_complete.execute(
        "SELECT COUNT(*) FROM v_textes WHERE devant_cc = 1"
    ).fetchone()[0]
    assert total >= 7


def test_facette_guadeloupe_forte_non_vide(base_complete) -> None:
    total = base_complete.execute(
        "SELECT COUNT(*) FROM textes WHERE guadeloupe_pertinence = 'forte'"
    ).fetchone()[0]
    assert total > 0


def test_facettes_combinees(base_complete) -> None:
    """`/recherche?statut=saisie_cc&guadeloupe=forte` doit rendre des résultats."""
    total = base_complete.execute(
        "SELECT COUNT(*) FROM v_textes WHERE devant_cc = 1 AND guadeloupe_pertinence = 'forte'"
    ).fetchone()[0]
    assert total > 0


def test_une_fiche_a_timeline_et_sources(base_complete) -> None:
    texte = _texte(base_complete, "loi-riposte")
    assert texte["nb_evenements"] >= 2
    assert texte["nb_sources"] >= 3


# ─────────────────────────────────────────────────────────────────────────────
# Honnêteté des données
# ─────────────────────────────────────────────────────────────────────────────


def test_les_deductions_sont_signalees(base_complete) -> None:
    """Toute valeur déduite porte un motif de vérification lisible."""
    lignes = base_complete.execute(
        "SELECT id, motif_verification FROM textes WHERE a_verifier = 1"
    )
    for ligne in lignes:
        assert ligne["motif_verification"], f"{ligne['id']} marqué à vérifier sans motif"


def test_aucune_pertinence_manuelle_n_a_ete_ecrasee(base_complete) -> None:
    """Les 27 lois promulguées gardent la cotation de l'annexe (§5.3)."""
    deduites = base_complete.execute(
        "SELECT COUNT(*) FROM textes WHERE statut = 'promulguee' "
        "AND motif_verification LIKE '%Pertinence Guadeloupe déduite%'"
    ).fetchone()[0]
    assert deduites == 0


def test_analyses_transversales_importees(base_complete) -> None:
    total = base_complete.execute("SELECT COUNT(*) FROM insights").fetchone()[0]
    assert total == 7


def test_echeances_du_calendrier(base_complete) -> None:
    codes = {
        r["code"] for r in base_complete.execute("SELECT code FROM echeances")
    }
    assert {"senatoriales-2026", "plf-2027", "facturation-electronique-reception"} <= codes
