"""Catálogo nomeado dos Agentics A0–A7 — Spec 027 + 029."""

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True)
class AgentProfile:
    id: str
    codename: str
    name: str
    role: str
    reads: tuple[str, ...]
    actions: tuple[str, ...]
    approval: str
    scenarios: tuple[str, ...] = ()


AGENT_CATALOG: dict[str, AgentProfile] = {
    "A0": AgentProfile(
        id="A0",
        codename="orchestrator",
        name="Maestro",
        role="Orquestrador multi-agente",
        reads=("todos os feeds", "action_log", "findings abertos", "threads activas"),
        actions=(
            "Delegar cenários aos agentes especializados",
            "Sintetizar estado global do ambiente Ligbox",
            "Abrir thread de coordenação entre agentes",
            "Escalar para humano quando confiança < limiar",
        ),
        approval="agentic_operator / ops_lead",
        scenarios=(),
    ),
    "A1": AgentProfile(
        id="A1",
        codename="node_health",
        name="Pulso",
        role="Saúde de nós e serviços Carbonio",
        reads=("métricas VM112", "CPU/RAM Proxmox", "status containers"),
        actions=(
            "Detectar serviço Carbonio/wizard down",
            "Criar finding + alerta ticket",
            "Sugerir restart (info auto; restart com ops_lead)",
        ),
        approval="auto (info) · ops_lead (restart)",
        scenarios=("wizard.vm112.bundle", "proxmox.cluster"),
    ),
    "A2": AgentProfile(
        id="A2",
        codename="infra_mail",
        name="Trilho",
        role="DNS, certificados, Traefik, nginx",
        reads=("DNS Cloudflare", "certs LE", "Traefik CT114", "SNI"),
        actions=(
            "Validar propagação DNS pós-onboard",
            "Detectar cert expirado ou mismatch SNI",
            "Propor fix DNS/Traefik (nunca aplicar sem devops/ops_lead)",
        ),
        approval="devops ou ops_lead antes de aplicar",
        scenarios=("pfsense.api.system",),
    ),
    "A3": AgentProfile(
        id="A3",
        codename="deliverability",
        name="Carta",
        role="SPF, DKIM, DMARC, reputação mail",
        reads=("registos DNS mail", "relatórios entregabilidade"),
        actions=(
            "Auditar SPF/DKIM/DMARC por domínio tenant",
            "Gerar relatório de entregabilidade",
            "Abrir finding para seo/technician revisão",
        ),
        approval="seo / technician revisão",
        scenarios=(),
    ),
    "A4": AgentProfile(
        id="A4",
        codename="security_mail",
        name="Escudo Mail",
        role="amavis, spam, clamav, filas mail",
        reads=("filas mail", "logs amavis/clamav", "quarentena"),
        actions=(
            "Detectar pico spam ou fila bloqueada",
            "Sugerir quarentena / release",
            "Correlacionar com alertas segurança VM112",
        ),
        approval="security_analyst",
        scenarios=(),
    ),
    "A5": AgentProfile(
        id="A5",
        codename="wazuh_soc",
        name="Sentinela SOC",
        role="Correlação SIEM Wazuh VM104",
        reads=("alertas Wazuh", "webhooks vm104", "tickets correlacionados"),
        actions=(
            "Correlacionar alerta L≥10 com domínio/sessão",
            "Enriquecer timeline do chamado",
            "Propor runbook R0/R1 segurança",
        ),
        approval="security_analyst / noc",
        scenarios=(),
    ),
    "A6": AgentProfile(
        id="A6",
        codename="support_copilot",
        name="Copiloto",
        role="Assistência tickets e janela humana",
        reads=("tickets Desk", "timeline onboarding", "findings", "KB specs"),
        actions=(
            "Rascunhar resposta ao cliente/ticket",
            "Responder janela /chat do operador humano",
            "Resumir contexto para technician enviar",
        ),
        approval="technician envia · agentic_operator vê tudo",
        scenarios=("funnel.stuck.onboarding",),
    ),
    "A7": AgentProfile(
        id="A7",
        codename="remediation",
        name="Remediador",
        role="Runbooks aprovados pós-incidente",
        reads=("playbooks aprovados", "findings critical/high", "aprovações pendentes"),
        actions=(
            "Propor runbook com confiança %",
            "Executar R0 auto (poll/refresh)",
            "Executar R1+ apenas após OK humano",
            "Registar action_executed na timeline",
        ),
        approval="agentic_operator obrigatório (R2/R3 dupla)",
        scenarios=(),
    ),
    "sentinel": AgentProfile(
        id="sentinel",
        codename="sentinel",
        name="Vigia",
        role="Health checks T0 — APIs e infra",
        reads=("endpoints HTTP", "integrações health", "Ollama", "VM123 stack"),
        actions=(
            "Executar cenários desk/wizard/pfsense/proxmox/ollama/VM123",
            "Criar findings com severidade",
            "Disparar e-mail em high/critical",
        ),
        approval="automático (detecção) · humano trata finding",
        scenarios=(
            "desk.api.health",
            "wizard.vm112.bundle",
            "pfsense.api.system",
            "integration.webhook.gap",
            "proxmox.cluster",
            "ollama.vm123.health",
            "vm123.finance.stack",
            "vm123.openpanel.bridge",
        ),
    ),
    "curator": AgentProfile(
        id="curator",
        codename="curator",
        name="Curador",
        role="Base de conhecimento (RAG)",
        reads=("specs/**/*.md", "agent_kb_chunks"),
        actions=("Indexar specs no SQLite", "Fornecer snippets ao Copiloto/Advisor"),
        approval="automático",
        scenarios=(),
    ),
}

# Map legacy agent_id in scenarios → A* principal
SCENARIO_AGENT_MAP = {
    "desk.api.health": "sentinel",
    "wizard.vm112.bundle": "A1",
    "pfsense.api.system": "A2",
    "funnel.stuck.onboarding": "A6",
    "integration.webhook.gap": "sentinel",
    "proxmox.cluster": "A1",
    "ollama.vm123.health": "sentinel",
    "vm123.finance.stack": "sentinel",
    "vm123.openpanel.bridge": "sentinel",
}


def resolve_agent(scenario_id: str, agent_id: str | None = None) -> AgentProfile:
    key = SCENARIO_AGENT_MAP.get(scenario_id) or agent_id or "sentinel"
    return AGENT_CATALOG.get(key, AGENT_CATALOG["sentinel"])


def roster_public() -> list[dict]:
    order = ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "sentinel", "curator"]
    out = []
    for k in order:
        if k not in AGENT_CATALOG:
            continue
        p = AGENT_CATALOG[k]
        out.append(
            {
                "id": p.id,
                "codename": p.codename,
                "name": p.name,
                "role": p.role,
                "reads": list(p.reads),
                "actions": list(p.actions),
                "approval": p.approval,
                "scenarios": list(p.scenarios),
            }
        )
    return out
