"""Assemblage déterministe du rapport d'audit 4Big.

Verdict global = PASS ssi (a) la couverture est bijective vs le CI (100% des
livrables gated, hors auditeur) ET (b) TOUS les modules audités atteignent
≥ 95/100 (aucun sous le seuil). Sinon FAIL — l'audit est un GATE, pas un rapport
indicatif. Le nombre de modules est DÉRIVÉ (`len(modules)` == `totals.modules`),
jamais figé ici : il croît quand un livrable est gated (17 → 22 à ce jour) sans
retoucher ce docstring.

Aucune date/horodatage → build reproductible + diffable (gate CI stable).
"""

from __future__ import annotations

from typing import Any

from . import registry, scoring

REPORT_NAME = "OTO QA · Audit 4Big Qualité"


def build(spec: dict[str, Any]) -> dict[str, Any]:
    coverage = registry.coverage_report(spec)
    modules = scoring.score_all(spec)

    scores = [m["score"] for m in modules]
    below = [m["id"] for m in modules if m["verdict"] != "PASS"]
    totals = {
        "modules": len(modules),
        "pass": sum(1 for m in modules if m["verdict"] == "PASS"),
        "fail": len(below),
        "min_score": min(scores) if scores else 0,
        "max_score": max(scores) if scores else 0,
        "pass_rate_pct": scoring._round_half_up(
            100.0 * sum(1 for m in modules if m["verdict"] == "PASS") / len(modules)
        ) if modules else 0,
    }

    verdict = "PASS" if (coverage["ok"] and not below) else "FAIL"

    return {
        "audit": REPORT_NAME,
        "version": spec["version"],
        "reference_cadre": spec["reference_cadre"],
        "pass_score": spec["thresholds"]["pass_score"],
        "coverage": coverage,
        "criteria": [
            {"id": c["id"], "label": c["label"], "weight": c["weight"]}
            for c in spec["criteria"]
        ],
        "modules": modules,
        "totals": totals,
        "verdict": verdict,
        "notes": spec.get("notes", []),
    }
