#!/usr/bin/env python3
"""Consolida os índices parciais das unidades em _indices/*.csv.

Cada agente escreve em _indices/parcial-<ID>/<nome>.csv (um arquivo por índice).
Este script valida cabeçalhos, remove duplicatas pela chave primária e grava os
arquivos canônicos em _indices/.

Uso:
  merge_indices.py [--check]   # --check valida sem escrever
"""

from __future__ import annotations

import argparse
import csv
import glob
import os
import sys

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
INDICES = os.path.join(ROOT, "_indices")

SCHEMAS = {
    "rotas.csv": (["id_rota", "unidade", "tipo", "metodo", "uri", "nome", "middleware",
                   "controlador", "acao", "permissao", "auth", "throttle", "cache",
                   "request", "resposta", "efeito", "fonte"], 0),
    "tabelas.csv": (["tabela", "unidade", "papel", "pk", "colunas", "fks", "indices",
                     "unique_constraints", "soft_delete", "uuid_fn", "migracoes",
                     "modelos", "consumidores", "escrita_em", "fonte"], 0),
    "componentes.csv": (["id", "unidade", "caminho_blade", "namespace", "props", "slots",
                         "eventos_js", "dom_ids", "consumidores", "a11y", "efeito",
                         "fonte"], 0),
    "permissoes.csv": (["slug", "unidade", "acao", "middleware", "role_padrao",
                        "onde_aplicada", "fonte"], 0),
    "config.csv": (["chave", "unidade", "default", "env", "tipo", "efeito",
                    "consumidores", "fonte"], 0),
    "dados-iniciais.csv": (["seeder", "unidade", "tabelas", "registros", "idempotencia",
                            "ordem", "fonte"], 0),
    "servicos.csv": (["unidade", "efeito", "api_publica", "ui_surface",
                      "particularidade", "consumidores", "precisa_reimplementacao",
                      "fonte"], 0),
    "arquivos.csv": (["caminho", "unidade", "doc", "papel", "status"], 0),
}


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("--check", action="store_true")
    args = ap.parse_args()

    partials = sorted(glob.glob(os.path.join(INDICES, "parcial-*", "*.csv")))
    if not partials:
        print("Nenhum índice parcial encontrado em _indices/parcial-*/")
        return 0

    errors: list[str] = []
    merged: dict[str, dict[str, list[str]]] = {name: {} for name in SCHEMAS}
    counts = {name: 0 for name in SCHEMAS}

    for path in partials:
        name = os.path.basename(path)
        rel = os.path.relpath(path, ROOT)
        if name not in SCHEMAS:
            errors.append(f"{rel}: índice desconhecido (esperado: {', '.join(SCHEMAS)})")
            continue
        expected, key_idx = SCHEMAS[name]
        with open(path, newline="", encoding="utf-8") as fh:
            reader = csv.reader(fh)
            header = next(reader, None)
            if header != expected:
                errors.append(f"{rel}: cabeçalho divergente\n  esperado: {','.join(expected)}\n  obtido:   {','.join(header or [])}")
                continue
            for lineno, row in enumerate(reader, start=2):
                if not row or all(not c.strip() for c in row):
                    continue
                if len(row) != len(expected):
                    errors.append(f"{rel}:{lineno}: {len(row)} colunas, esperado {len(expected)}")
                    continue
                key = row[key_idx].strip()
                if name == "rotas.csv":
                    key = f"{row[3]}|{row[4]}|{row[5]}"
                if not key:
                    errors.append(f"{rel}:{lineno}: chave vazia")
                    continue
                counts[name] += 1
                merged[name].setdefault(key, row)

    if not args.check and not errors:
        for name, rows in merged.items():
            out = os.path.join(INDICES, name)
            with open(out, "w", newline="", encoding="utf-8") as fh:
                writer = csv.writer(fh)
                writer.writerow(SCHEMAS[name][0])
                for key in sorted(rows):
                    writer.writerow(rows[key])
            print(f"{name}: {len(rows)} linhas")

    print(f"Parciais lidos: {len(partials)} | linhas: {counts}")
    if errors:
        print("\nERROS:")
        for err in errors:
            print(f"  - {err}")
        return 1
    print("Índices OK")
    return 0


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