#!/usr/bin/env python3
"""Conferir coerência formal do relatório; não julga o conteúdo das fontes."""
from pathlib import Path
import json
import sys

def validate_report(report, checklist):
    if not isinstance(report, dict):
        raise ValueError("O relatório deve ser um objeto JSON.")
    if report.get("checklist_version") != checklist["checklist_version"]:
        raise ValueError("Versão do checklist diferente da captura usada.")
    if not isinstance(report.get("agent"), dict) or not isinstance(report["agent"].get("name"), str) or not report["agent"]["name"].strip():
        raise ValueError("Identifique o agente no alcance da conferência.")
    if not isinstance(report.get("scope"), dict):
        raise ValueError("scope deve ser um objeto.")
    kind = report["scope"].get("kind")
    if kind not in ("completa", "focal"):
        raise ValueError("scope.kind deve ser completa ou focal.")
    expected = {}
    by_dimension = {}
    for dimension in checklist["dimensions"]:
        by_dimension[dimension["field"]] = {c["id"] for c in dimension["criteria"]}
        for criterion in dimension["criteria"]:
            expected[criterion["id"]] = dimension["field"]
    rows = report.get("criteria")
    if not isinstance(rows, list) or not rows:
        raise ValueError("Informe os critérios efetivamente examinados.")
    seen = {}
    for row in rows:
        if not isinstance(row, dict):
            raise ValueError("Cada critério deve ser um objeto.")
        key = row.get("id")
        if key not in expected:
            raise ValueError(f"Critério fora do instrumento: {key}")
        if key in seen:
            raise ValueError(f"Critério repetido: {key}")
        status = row.get("status")
        if status is not None and status not in checklist["rating_values"]:
            raise ValueError(f"Situação inválida em {key}: {status}")
        references = row.get("references", [])
        if not isinstance(references, list) or any(not isinstance(v,str) or not v.strip() for v in references):
            raise ValueError(f"Referências inválidas em {key}.")
        if "notes" in row and not isinstance(row["notes"], str):
            raise ValueError(f"Sustentação deve ser texto em {key}.")
        if status in ("Em ordem", "Ajustar") and (not isinstance(row.get("notes"), str) or not row["notes"].strip()):
            raise ValueError(f"Falta sustentação textual em {key}.")
        if status in ("Em ordem", "Ajustar") and not references:
            raise ValueError(f"Falta referência examinada em {key}.")
        if status == "Ajustar" and (not isinstance(row.get("adjustment"), str) or not row["adjustment"].strip()):
            raise ValueError(f"Falta ajuste concreto em {key}.")
        if status == "Não se aplica" and (not isinstance(row.get("reason"), str) or not row["reason"].strip()):
            raise ValueError(f"Falta motivo de dispensa em {key}.")
        if status is None and (not isinstance(row.get("notes"), str) or not row["notes"].strip()):
            raise ValueError(f"Registre a dependência ou ausência de conclusão em {key}.")
        seen[key] = row
    if kind == "completa" and set(seen) != set(expected):
        missing = sorted(set(expected) - set(seen))
        raise ValueError("Conferência completa sem todos os critérios: " + ", ".join(missing))
    results = {}
    for field, keys in by_dimension.items():
        present = [seen[key] for key in keys if key in seen]
        if any(row.get("status") == "Ajustar" for row in present):
            result = "Ajustar"
        elif not keys.issubset(seen) or any(row.get("status") is None for row in present):
            result = None
        elif all(row["status"] == "Não se aplica" for row in present):
            result = "Não se aplica"
        else:
            result = "Em ordem"
        results[field] = result
    supplied = report.get("dimension_results", {})
    if not isinstance(supplied, dict):
        raise ValueError("dimension_results deve ser um objeto quando informado.")
    for field, value in supplied.items():
        if field not in results or value != results[field]:
            raise ValueError(f"Síntese incompatível na dimensão {field}.")
    if not isinstance(report.get("priority_adjustment", ""), str):
        raise ValueError("priority_adjustment deve ser texto.")
    return {
        "checklist_version": checklist["checklist_version"],
        "scope_kind": kind,
        "criteria_recorded": len(seen),
        "pending_criteria": sorted(key for key, row in seen.items() if row.get("status") is None),
        "unexamined_criteria": sorted(set(expected) - set(seen)),
        "dimension_results": results,
        "priority_adjustment": report.get("priority_adjustment", ""),
        "limit": "Coerência formal; a leitura das fontes e o julgamento são do responsável."
    }

def main():
    if len(sys.argv) != 2:
        print("Uso: python3 conferir-relatorio.py RELATORIO.json", file=sys.stderr)
        return 2
    try:
        root = Path(__file__).resolve().parents[1]
        checklist = json.loads((root / "references/criterios.json").read_text())
        report = json.loads(Path(sys.argv[1]).read_text())
        print(json.dumps(validate_report(report, checklist), ensure_ascii=False, indent=2))
        return 0
    except (OSError, ValueError, KeyError, TypeError) as error:
        print(json.dumps({"error": str(error)}, ensure_ascii=False), file=sys.stderr)
        return 2

if __name__ == "__main__":
    raise SystemExit(main())

