"""Artifact writers for the Mais Humana governance layer."""

from __future__ import annotations

import json
from dataclasses import dataclass
from pathlib import Path
from typing import Callable, Iterable, Sequence

from .evidence_graph import EvidenceGraph, graph_dot, graph_markdown, graph_rows
from .exit_order_compiler import CompiledOrderSet, compiled_orders_markdown, order_coverage_rows, source_candidate_rows
from .governance_engine import (
    EcosystemGovernancePortfolio,
    compact_governance_payload,
    governance_candidates_markdown,
    governance_cards_csv,
    governance_checks_csv,
    governance_portfolio_markdown,
    governance_to_plain_data,
    rows_to_csv,
)
from .governance_scenarios import ScenarioPortfolio, scenario_rows, scenarios_markdown
from .human_readiness_registry import ReadinessRegistry, registry_markdown, registry_rows
from .models import GeneratedFile, as_plain_data
from .portfolio_queries import PortfolioQuestion, compact_question_payload, questions_markdown, questions_rows
from .round_assurance import AssuranceSuite, assurance_markdown, assurance_rows
from .runtime_budget import RoundLineBudget, budget_markdown, budget_rows
from .service_order_lifecycle import RoundExecutionPackage, lifecycle_audit_markdown, lifecycle_execution_markdown, lifecycle_pending_markdown, lifecycle_queue_markdown
from .workflow_registry import WorkflowPortfolio, workflow_markdown, workflow_rows


@dataclass(slots=True)
class GovernanceExport:
    path: Path
    description: str
    function: str
    file_type: str
    writer: Callable[[Path], None]


@dataclass(slots=True)
class GovernanceExportBundle:
    files: tuple[Path, ...]
    generated_records: tuple[GeneratedFile, ...]
    errors: tuple[str, ...]

    def to_dict(self) -> dict[str, object]:
        return {
            "files": [str(path) for path in self.files],
            "generated_records": [item.to_dict() for item in self.generated_records],
            "errors": self.errors,
        }


def write_json(path: Path, payload: object) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(json.dumps(as_plain_data(payload), ensure_ascii=False, indent=2, sort_keys=True), encoding="utf-8")


def write_text(path: Path, text: str) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(text, encoding="utf-8")


def record_for(path: Path, project_root: Path, description: str, function: str, file_type: str, relation_to_order: str) -> GeneratedFile:
    try:
        rel = path.relative_to(project_root)
    except ValueError:
        rel = path
    return GeneratedFile(
        path=str(rel).replace("\\", "/"),
        description=description,
        function=function,
        file_type=file_type,
        changed_by="mais_humana.governance_exports",
        change_summary=description,
        relation_to_order=relation_to_order,
    )


def export(
    relative_path: str,
    description: str,
    function: str,
    file_type: str,
    writer: Callable[[Path], None],
    root: Path,
) -> GovernanceExport:
    return GovernanceExport(
        path=root / relative_path,
        description=description,
        function=function,
        file_type=file_type,
        writer=writer,
    )


def governance_exports(
    project_root: Path,
    portfolio: EcosystemGovernancePortfolio,
    registry: ReadinessRegistry,
    workflows: WorkflowPortfolio,
    scenarios: ScenarioPortfolio,
    graph: EvidenceGraph,
    questions: Sequence[PortfolioQuestion],
    budget: RoundLineBudget | None = None,
    compiled_orders: CompiledOrderSet | None = None,
    lifecycle: RoundExecutionPackage | None = None,
    assurance: AssuranceSuite | None = None,
) -> tuple[GovernanceExport, ...]:
    exports: list[GovernanceExport] = [
        export("dados/governanca-operacional.json", "Portfolio completo de governanca operacional.", "governanca", "json", lambda path: write_json(path, governance_to_plain_data(portfolio)), project_root),
        export("dados/governanca-operacional-compacta.json", "Portfolio compacto de governanca operacional.", "governanca compacta", "json", lambda path: write_json(path, compact_governance_payload(portfolio)), project_root),
        export("ecossistema/GOVERNANCA-OPERACIONAL-MAIS-HUMANA.md", "Relatorio de governanca operacional.", "governanca", "markdown", lambda path: write_text(path, governance_portfolio_markdown(portfolio)), project_root),
        export("ecossistema/CANDIDATAS-OS-GOVERNANCA.md", "Candidatas de OS por governanca.", "ordens candidatas", "markdown", lambda path: write_text(path, governance_candidates_markdown(portfolio)), project_root),
        export("matrizes/governanca-cards.csv", "Cards de governanca em CSV.", "matriz governanca", "csv", lambda path: write_text(path, governance_cards_csv(portfolio)), project_root),
        export("matrizes/governanca-checks.csv", "Checks de governanca em CSV.", "matriz governanca", "csv", lambda path: write_text(path, governance_checks_csv(portfolio)), project_root),
        export("dados/registro-prontidao-humana.json", "Registro plataforma x perfil x governanca.", "registro prontidao", "json", lambda path: write_json(path, registry), project_root),
        export("ecossistema/REGISTRO-PRONTIDAO-HUMANA.md", "Registro humano de prontidao por perfil.", "registro prontidao", "markdown", lambda path: write_text(path, registry_markdown(registry)), project_root),
        export("matrizes/registro-prontidao-humana.csv", "Registro humano em CSV.", "registro prontidao", "csv", lambda path: write_text(path, rows_to_csv(registry_rows(registry))), project_root),
        export("dados/workflows-humanos.json", "Workflows humanos em JSON.", "workflows", "json", lambda path: write_json(path, workflows), project_root),
        export("ecossistema/WORKFLOWS-HUMANOS-OPERACIONAIS.md", "Workflows humanos operacionais.", "workflows", "markdown", lambda path: write_text(path, workflow_markdown(workflows)), project_root),
        export("matrizes/workflows-humanos.csv", "Workflows humanos em CSV.", "workflows", "csv", lambda path: write_text(path, rows_to_csv(workflow_rows(workflows))), project_root),
        export("dados/cenarios-governanca.json", "Cenarios de aceite de governanca.", "cenarios", "json", lambda path: write_json(path, scenarios), project_root),
        export("ecossistema/CENARIOS-ACEITE-GOVERNANCA.md", "Cenarios de aceite de governanca.", "cenarios", "markdown", lambda path: write_text(path, scenarios_markdown(scenarios)), project_root),
        export("matrizes/cenarios-governanca.csv", "Cenarios de governanca em CSV.", "cenarios", "csv", lambda path: write_text(path, rows_to_csv(scenario_rows(scenarios))), project_root),
        export("dados/grafo-evidencias.json", "Grafo de evidencias em JSON.", "grafo evidencias", "json", lambda path: write_json(path, graph), project_root),
        export("ecossistema/GRAFO-EVIDENCIAS-MAIS-HUMANA.md", "Grafo de evidencias em Markdown.", "grafo evidencias", "markdown", lambda path: write_text(path, graph_markdown(graph)), project_root),
        export("graficos/grafo-evidencias.dot", "Grafo de evidencias em DOT.", "grafo evidencias", "dot", lambda path: write_text(path, graph_dot(graph)), project_root),
        export("matrizes/grafo-evidencias.csv", "Grafo de evidencias em CSV.", "grafo evidencias", "csv", lambda path: write_text(path, rows_to_csv(graph_rows(graph))), project_root),
        export("dados/perguntas-governanca.json", "Perguntas operacionais sobre governanca.", "perguntas governanca", "json", lambda path: write_json(path, compact_question_payload(questions)), project_root),
        export("ecossistema/PERGUNTAS-OPERACIONAIS-GOVERNANCA.md", "Perguntas operacionais sobre governanca.", "perguntas governanca", "markdown", lambda path: write_text(path, questions_markdown(questions)), project_root),
        export("matrizes/perguntas-governanca.csv", "Perguntas de governanca em CSV.", "perguntas governanca", "csv", lambda path: write_text(path, rows_to_csv(questions_rows(questions))), project_root),
    ]
    if budget is not None:
        exports.extend(
            [
                export("dados/budget-linhas-rodada.json", "Budget de linhas da rodada.", "budget linhas", "json", lambda path: write_json(path, budget), project_root),
                export("ecossistema/BUDGET-LINHAS-RODADA.md", "Budget de linhas da rodada.", "budget linhas", "markdown", lambda path: write_text(path, budget_markdown(budget)), project_root),
                export("matrizes/budget-linhas-rodada.csv", "Budget de linhas em CSV.", "budget linhas", "csv", lambda path: write_text(path, rows_to_csv(budget_rows(budget))), project_root),
            ]
        )
    if compiled_orders is not None:
        exports.extend(
            [
                export("dados/ordens-governanca-compiladas.json", "Ordens compiladas por governanca.", "ordens compiladas", "json", lambda path: write_json(path, compiled_orders), project_root),
                export("ecossistema/ORDENS-GOVERNANCA-COMPILADAS.md", "Ordens compiladas por governanca.", "ordens compiladas", "markdown", lambda path: write_text(path, compiled_orders_markdown(compiled_orders)), project_root),
                export("matrizes/ordens-governanca-compiladas.csv", "Ordens compiladas em CSV.", "ordens compiladas", "csv", lambda path: write_text(path, rows_to_csv(order_coverage_rows(compiled_orders))), project_root),
                export("matrizes/candidatas-governanca-usadas.csv", "Candidatas usadas em ordens compiladas.", "ordens compiladas", "csv", lambda path: write_text(path, rows_to_csv(source_candidate_rows(compiled_orders))), project_root),
            ]
        )
    if lifecycle is not None:
        exports.extend(
            [
                export("dados/lifecycle-ordens-ativas.json", "Lifecycle de ordens ativas.", "lifecycle ordens", "json", lambda path: write_json(path, lifecycle), project_root),
                export("ecossistema/LIFECYCLE-ORDENS-ATIVAS.md", "Lifecycle de ordens ativas.", "lifecycle ordens", "markdown", lambda path: write_text(path, lifecycle_execution_markdown(lifecycle)), project_root),
                export("ecossistema/PENDENCIAS-LIFECYCLE-ORDENS.md", "Pendencias do lifecycle de ordens.", "lifecycle ordens", "markdown", lambda path: write_text(path, lifecycle_pending_markdown(lifecycle)), project_root),
                export("ecossistema/AUDITORIA-LIFECYCLE-ORDENS.md", "Auditoria do lifecycle de ordens.", "lifecycle ordens", "markdown", lambda path: write_text(path, lifecycle_audit_markdown(lifecycle)), project_root),
                export("ecossistema/FILA-ATIVA-LIFECYCLE.md", "Fila ativa do lifecycle.", "lifecycle ordens", "markdown", lambda path: write_text(path, lifecycle_queue_markdown(lifecycle)), project_root),
            ]
        )
    if assurance is not None:
        exports.extend(
            [
                export("dados/assurance-rodada.json", "Assurance da rodada em JSON.", "assurance", "json", lambda path: write_json(path, assurance), project_root),
                export("ecossistema/ASSURANCE-RODADA-MAIS-HUMANA.md", "Assurance da rodada.", "assurance", "markdown", lambda path: write_text(path, assurance_markdown(assurance)), project_root),
                export("matrizes/assurance-rodada.csv", "Assurance da rodada em CSV.", "assurance", "csv", lambda path: write_text(path, rows_to_csv(assurance_rows(assurance))), project_root),
            ]
        )
    return tuple(exports)


def write_governance_exports(
    project_root: Path,
    exports: Sequence[GovernanceExport],
    relation_to_order: str,
) -> GovernanceExportBundle:
    written: list[Path] = []
    records: list[GeneratedFile] = []
    errors: list[str] = []
    for item in exports:
        try:
            item.writer(item.path)
            written.append(item.path)
            records.append(record_for(item.path, project_root, item.description, item.function, item.file_type, relation_to_order))
        except OSError as exc:
            errors.append(f"{item.path}: {exc}")
    return GovernanceExportBundle(files=tuple(written), generated_records=tuple(records), errors=tuple(errors))


def central_lifecycle_exports(platform_folder: Path, lifecycle: RoundExecutionPackage) -> tuple[GovernanceExport, ...]:
    return (
        export("reports/EXECUTADO__fechamento-ordens-ativas.md", "Fechamento das ordens ativas.", "lifecycle ordens", "markdown", lambda path: write_text(path, lifecycle_execution_markdown(lifecycle)), platform_folder),
        export("reports/PENDENCIAS-CODEX__fechamento-ordens-ativas.md", "Pendencias do fechamento das ordens.", "lifecycle ordens", "markdown", lambda path: write_text(path, lifecycle_pending_markdown(lifecycle)), platform_folder),
        export("audit/AUDITORIA-GPT__fechamento-ordens-ativas.md", "Auditoria do fechamento das ordens.", "lifecycle ordens", "markdown", lambda path: write_text(path, lifecycle_audit_markdown(lifecycle)), platform_folder),
        export("current/active-order-queue.md", "Fila ativa apos rodada.", "fila ativa", "markdown", lambda path: write_text(path, lifecycle_queue_markdown(lifecycle)), platform_folder),
        export("indexes/orders-lifecycle-index.md", "Indice lifecycle das ordens.", "indice ordens", "markdown", lambda path: write_text(path, lifecycle_execution_markdown(lifecycle)), platform_folder),
    )


def write_central_lifecycle_exports(platform_folder: Path, lifecycle: RoundExecutionPackage) -> tuple[Path, ...]:
    written: list[Path] = []
    for item in central_lifecycle_exports(platform_folder, lifecycle):
        item.writer(item.path)
        written.append(item.path)
    return tuple(written)
