#!/usr/bin/env python3
"""Valida a árvore sucesu_analise/v7_implementation.

- toda pasta de unidade tem README.md;
- front-matter mínimo e valores válidos;
- seções obrigatórias;
- sem placeholders;
- código suficiente;
- links relativos resolvem.

Uso: python3 tools/check_impl.py [--json]
"""
from __future__ import annotations

import json
import os
import re
import sys

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
IMPL = os.path.join(ROOT, "v7_implementation")
SKIP = {"_contract", "_template"}
REQUIRED_KEYS = ["id", "tipo", "status", "token", "camada", "unidade_fonte", "adrs", "depende_de"]
TIPOS = {"core", "service", "module", "ui", "feature", "data"}
CAMADAS = {"core", "services", "layout", "modules", "data"}
SECTIONS = [
    "Contrato", "Estrutura alvo", "Implementação", "Dados e migração",
    "Fluxos e estados", "Segurança e limites", "Testes", "Validação", "Aceite",
    "Riscos e armadilhas", "Evidências",
]
LINK = re.compile(r"\]\(([^)#]+\.md)(?:#[^)]*)?\)")
FENCE = re.compile(r"^```(php|blade|sql|bash|js|json|yaml|text)\b", re.MULTILINE)
PLACEHOLDERS = ("TODO", "PREENCHER", "FIXME", "implementar depois")


def front_matter(text: str) -> dict:
    if not text.startswith("---\n"):
        return {}
    end = text.find("\n---", 4)
    if end == -1:
        return {}
    meta: dict = {}
    key = None
    for line in text[4:end].splitlines():
        if not line.strip():
            continue
        if line.startswith(("  - ", "- ")):
            if key:
                meta.setdefault(key, [])
                if isinstance(meta[key], list):
                    meta[key].append(line.split("- ", 1)[1].strip())
            continue
        if ":" in line:
            key, value = line.split(":", 1)
            key = key.strip()
            value = value.strip().strip('"\'')
            meta[key] = value
    return meta


def main() -> int:
    errors: dict[str, list[str]] = {}
    checked = 0
    for dirpath, dirnames, filenames in os.walk(IMPL):
        dirnames[:] = [d for d in dirnames if d not in SKIP]
        if os.path.basename(dirpath) in SKIP:
            continue
        rel = os.path.relpath(dirpath, IMPL)
        if rel == ".":
            continue
        # só pastas-folha de unidade
        if any(os.path.isdir(os.path.join(dirpath, d)) for d in dirnames):
            continue
        readme = os.path.join(dirpath, "README.md")
        if not os.path.exists(readme):
            errors.setdefault(os.path.relpath(dirpath, ROOT), []).append("sem README.md")
            continue
        checked += 1
        text = open(readme, encoding="utf-8").read()
        meta = front_matter(text)
        errs: list[str] = []
        if not meta:
            errs.append("sem front-matter")
        for key in REQUIRED_KEYS:
            if key not in meta or meta[key] in ("", []):
                errs.append(f"front-matter sem '{key}'")
        if meta.get("tipo") not in TIPOS:
            errs.append(f"tipo inválido: {meta.get('tipo')!r}")
        if meta.get("camada") not in CAMADAS:
            errs.append(f"camada inválida: {meta.get('camada')!r}")
        if meta.get("status") != "pronto":
            errs.append("status deve ser 'pronto'")
        body = text.split("\n---", 1)[-1]
        for section in SECTIONS:
            if not re.search(rf"^##\s+.*{re.escape(section)}", body, re.M):
                errs.append(f"seção ausente: {section}")
        for p in PLACEHOLDERS:
            if p in text:
                errs.append(f"placeholder: {p}")
        fences = len(FENCE.findall(body))
        if fences < 3:
            errs.append(f"poucos trechos de código: {fences}")
        lines = len(text.splitlines())
        if lines < 180:
            errs.append(f"documento curto: {lines} linhas")
        for target in LINK.findall(body):
            if target.startswith(("http://", "https://")):
                continue
            resolved = os.path.normpath(os.path.join(os.path.dirname(readme), target))
            if not os.path.exists(resolved):
                errs.append(f"link quebrado: {target}")
        if errs:
            errors[os.path.relpath(readme, ROOT)] = errs
    if "--json" in sys.argv:
        print(json.dumps(errors, ensure_ascii=False, indent=2))
    else:
        print(f"Unidades verificadas: {checked} | com erro: {len(errors)}")
        for path, errs in errors.items():
            print(f"\n{path}")
            for e in errs:
                print(f"  - {e}")
    return 1 if errors else 0


if __name__ == "__main__":
    sys.exit(main())
