"""Central dossier materialization for service-order closeout.

Earlier rounds may update ``current/active-order-queue.md`` faster than the
central can write the matching order files, especially when ACLs or SQLite locks
interrupt the closeout.  This module makes that gap explicit and repairable:
it materializes the active orders mentioned by the queue, creates the next
continuity orders, writes a compact closeout report, and updates the semantic
SQLite when the filesystem allows it.
"""

from __future__ import annotations

import json
import sqlite3
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
from typing import Any, Mapping, Sequence

from .identity_policy import CANONICAL_COMPATIBILITY_RULE, CANONICAL_PROJECT_ID, CENTRAL_FOLDER_NAME, CURRENT_PROJECT_ID
from .models import GeneratedFile, OrderStatus, OrderType, ServiceOrder, as_plain_data, merge_unique, utc_now
from .orders import order_markdown
from .storage import connect, upsert_files, upsert_orders


PROJECT_ID = CANONICAL_PROJECT_ID
REAL_REPO = CURRENT_PROJECT_ID


class MaterializationStatus(str, Enum):
    """Result for one central materialization action."""

    CREATED = "created"
    UPDATED = "updated"
    EXISTS = "exists"
    FAILED = "failed"
    SKIPPED = "skipped"


class OrderLifecycleRole(str, Enum):
    """Role of one order in this repair pass."""

    ACTIVE_INPUT = "active_input"
    NEXT_OUTPUT = "next_output"


@dataclass(frozen=True, slots=True)
class MaterializedOrderSpec:
    """Declarative service-order spec used to materialize central files."""

    order_id: str
    order_type: OrderType
    title: str
    purpose: str
    object_scope: str
    reason: str
    expected_result: str
    affected_paths: tuple[str, ...]
    validations: tuple[str, ...]
    ready_criteria: tuple[str, ...]
    role: OrderLifecycleRole
    status: OrderStatus = OrderStatus.PLANNED
    priority: str = "alta"

    @property
    def subfolder(self) -> str:
        return "executivas" if self.order_type == OrderType.EXECUTIVE else "gerenciais"

    @property
    def filename(self) -> str:
        return f"{self.order_id}.md"

    def to_order(self) -> ServiceOrder:
        return ServiceOrder(
            order_id=self.order_id,
            order_type=self.order_type,
            project_id=PROJECT_ID,
            title=self.title,
            purpose=self.purpose,
            object_scope=self.object_scope,
            reason=self.reason,
            expected_result=self.expected_result,
            affected_paths=self.affected_paths,
            validations=self.validations,
            ready_criteria=self.ready_criteria,
            status=self.status,
            priority=self.priority,
        )

    def to_dict(self) -> dict[str, Any]:
        return as_plain_data(self)


@dataclass(frozen=True, slots=True)
class MaterializedOrderAction:
    """Result of writing one service-order file."""

    order_id: str
    role: OrderLifecycleRole
    path: str
    status: MaterializationStatus
    error: str = ""

    def to_dict(self) -> dict[str, Any]:
        return as_plain_data(self)


@dataclass(frozen=True, slots=True)
class SemanticWriteResult:
    """Result of updating central semantic SQLite."""

    sqlite_path: str
    attempted: bool
    ok: bool
    files_count: int
    orders_count: int
    error: str = ""

    def to_dict(self) -> dict[str, Any]:
        return as_plain_data(self)


@dataclass(frozen=True, slots=True)
class CentralMaterializationReport:
    """Full materialization report for the central platform folder."""

    report_id: str
    generated_at: str
    project_id: str
    central_platform_folder: str
    project_root: str
    active_input_orders: tuple[MaterializedOrderSpec, ...]
    next_output_orders: tuple[MaterializedOrderSpec, ...]
    actions: tuple[MaterializedOrderAction, ...]
    semantic_write: SemanticWriteResult
    summary: tuple[str, ...]
    blockers: tuple[str, ...]
    generated_files: tuple[str, ...] = ()
    fallback_order_files: tuple[str, ...] = ()
    local_semantic_write: SemanticWriteResult | None = None

    @property
    def status(self) -> MaterializationStatus:
        if any(action.status == MaterializationStatus.FAILED for action in self.actions) or not self.semantic_write.ok:
            return MaterializationStatus.FAILED
        if any(action.status == MaterializationStatus.CREATED for action in self.actions):
            return MaterializationStatus.CREATED
        return MaterializationStatus.EXISTS

    def to_dict(self) -> dict[str, Any]:
        data = as_plain_data(self)
        data["status"] = self.status.value
        return data


def _exec(
    order_id: str,
    title: str,
    purpose: str,
    reason: str,
    expected: str,
    affected: Sequence[str],
    validations: Sequence[str],
    ready: Sequence[str],
    *,
    role: OrderLifecycleRole,
    status: OrderStatus = OrderStatus.PLANNED,
) -> MaterializedOrderSpec:
    return MaterializedOrderSpec(
        order_id=order_id,
        order_type=OrderType.EXECUTIVE,
        title=title,
        purpose=purpose,
        object_scope="Projeto real Mais Humana, MCPs Internos, pasta central da plataforma 15 e artefatos de evidencia MCP.",
        reason=reason,
        expected_result=expected,
        affected_paths=tuple(affected),
        validations=tuple(validations),
        ready_criteria=tuple(ready),
        role=role,
        status=status,
    )


def _mgr(
    order_id: str,
    title: str,
    purpose: str,
    reason: str,
    expected: str,
    affected: Sequence[str],
    validations: Sequence[str],
    ready: Sequence[str],
    *,
    role: OrderLifecycleRole,
    status: OrderStatus = OrderStatus.PLANNED,
) -> MaterializedOrderSpec:
    return MaterializedOrderSpec(
        order_id=order_id,
        order_type=OrderType.MANAGERIAL,
        title=title,
        purpose=purpose,
        object_scope="Dossie gerencial da plataforma 15, politicas MCP-only, sincronizacao, nome canonico, Docs e runner operacional.",
        reason=reason,
        expected_result=expected,
        affected_paths=tuple(affected),
        validations=tuple(validations),
        ready_criteria=tuple(ready),
        role=role,
        status=status,
    )


def active_input_order_specs() -> tuple[MaterializedOrderSpec, ...]:
    """Return the active orders that the queue references but may not hold."""

    return (
        _exec(
            "0037_EXECUTIVA__homologar-rotas-administrativas-mcp-no-gateway",
            "Homologar rotas administrativas MCP no gateway",
            "Validar que consulta, diagnostico, acao, auditoria e explicacao interplataforma estejam descritas e auditaveis pelo MCP.",
            "A fila ativa citou a homologacao das rotas administrativas, mas os arquivos de ordem nao estavam materializados.",
            "Catalogo de aceitacao MCP-only gerado, indexado e registrado com source hashes, traceId/auditId e evidencias.",
            (
                "src/mais_humana/mcp_admin_route_acceptance.py",
                "src/mais_humana/generated_mcp_admin_route_acceptance.py",
                "dados/mcp-admin-route-acceptance.json",
            ),
            (
                "python tools/generate_mcp_admin_route_acceptance.py",
                "python -m mais_humana.cli mcp-admin-route-acceptance",
                "python -m unittest tests.test_mcp_admin_route_acceptance",
            ),
            (
                "rotas administrativas materializadas em catalogo Python",
                "artefatos JSON/CSV/Markdown gerados",
                "relacao MCP-only documentada na central",
            ),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.PARTIAL,
        ),
        _exec(
            "0038_EXECUTIVA__corrigir-acl-index-lock-e-commitar-artefatos-mcp",
            "Corrigir ACL index.lock e commitar artefatos MCP",
            "Permitir commit e push dos artefatos MCP sem reset, restore ou sobrescrita de alteracao valida.",
            "Fetch/push continuam bloqueados por Schannel e locks/ACL de Git em espelhos Windows.",
            "Credenciais e ACL corrigidas por operador autorizado; commit e push escopados executados depois de status limpo.",
            (".git/index.lock", ".git/FETCH_HEAD", "dados/targeted-sync-audit.json"),
            ("git status --short --branch", "git fetch --all --prune", "git push origin main"),
            ("credencial Git valida", "locks removidos por owner autorizado", "push confirmado por hash remoto"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.BLOCKED,
        ),
        _exec(
            "0039_EXECUTIVA__reexecutar-wrangler-em-runner-homologado-e-registrar-deploy",
            "Reexecutar Wrangler em runner homologado e registrar deploy",
            "Separar deploy Cloudflare real do plugin e confirmar publicacao por evidencia operacional.",
            "A ordem roteadora informa que deploy esta sendo feito manualmente pelo usuario; este executor deve apenas conferir live.",
            "Runner oficial ou deploy manual registrado com deployment id, smoke live e rollback conhecido.",
            ("dados/mcp-publication-gate-mais-humana.json", "ecossistema/MCP-PUBLICATION-GATE-MAIS-HUMANA.md"),
            ("validar endpoint /v1/execute", "registrar deployment observado", "nao usar plugin como diagnostico operacional"),
            ("deploy confirmado por wrangler ou evidencia manual", "smoke live ok", "rollback documentado"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.PARTIAL,
        ),
        _exec(
            "0040_EXECUTIVA__materializar-escrita-central-e-sql-semantico-sem-permissionerror",
            "Materializar escrita central e SQL semantico sem PermissionError",
            "Garantir que a central receba ordens, indices, reports e funcao semantica dos arquivos quando houver permissao.",
            "Ordens ativas estavam citadas nos indices, mas nao existiam como arquivos fisicos.",
            "Ordens ativas e de saida materializadas; SQLite central atualizado ou falha objetiva registrada.",
            (
                "orders/executivas",
                "orders/gerenciais",
                "controle-semantico.sqlite",
                "reports/EXECUTADO__rodada-015-central-materialization-2026-05-02.md",
            ),
            ("verificar existencia dos arquivos de ordem", "consultar sql-counts", "git status final"),
            ("ordens fisicas existem", "SQL semantico atualizado ou pendencia real registrada", "indices/current/status reconciliados"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.PARTIAL,
        ),
        _exec(
            "0041_EXECUTIVA__resolver-test-tmp-bloqueado-por-acl",
            "Resolver test-tmp bloqueado por ACL",
            "Remover ou formalizar diretorios temporarios que o executor comum nao consegue apagar.",
            "A higiene anterior reduziu .test-tmp, mas dois diretorios continuaram retidos por WinError 5.",
            "Artefato temporario removido por owner autorizado ou registrado como bloqueio ACL externo com evidencia.",
            (".test-tmp", "dados/workspace-hygiene-report.json", "ecossistema/WORKSPACE-HYGIENE-REPORT.md"),
            ("python -m mais_humana.cli workspace-hygiene --apply", "verificar ausencia de node_modules", "git status"),
            ("node_modules ausente", ".test-tmp ausente ou blocker ACL explicito", "relatorio de higiene atualizado"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.PARTIAL,
        ),
    )


def active_managerial_order_specs() -> tuple[MaterializedOrderSpec, ...]:
    """Return managerial active orders that must exist physically."""

    return (
        _mgr(
            "0049_GERENCIAL__homologar-mcp-only-administration-routes-como-politica-de-ecossistema",
            "Homologar MCP-only administration routes como politica de ecossistema",
            "Transformar a regra MCP-only em politica de governanca para todas as plataformas.",
            "O roteador determinou que toda comunicacao e administracao interplataforma passe pelos MCPs Internos.",
            "Politica MCP-only formalizada com rastreabilidade, gates e criterios de excecao.",
            ("ecossistema/MCP-ADMIN-ROUTE-ACCEPTANCE.md", "indexes/orders-index.md"),
            ("avaliar contratos MCP-only", "confirmar traceId/auditId", "registrar excecoes"),
            ("politica formal registrada", "rotas e operacoes mapeadas", "bloqueios externos separados"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.PARTIAL,
        ),
        _mgr(
            "0050_GERENCIAL__decidir-politica-de-sync-automatico-e-credencial-gitea",
            "Decidir politica de sync automatico e credencial Gitea",
            "Definir quem corrige credenciais/ACL e como a sincronizacao automatica preserva alteracao valida mais recente.",
            "A sincronizacao permanente falhou por SEC_E_NO_CREDENTIALS e Permission denied em FETCH_HEAD.",
            "Decisao institucional sobre credencial, servico automatico, bloqueio destrutivo e evidencias de sync.",
            ("dados/repository-mesh-readiness.json", "dados/targeted-sync-audit.json"),
            ("comparar hashes", "registrar ahead/behind", "bloquear reset/rebase automatico"),
            ("credencial operacional definida", "politica anti-reversao aprovada", "logs de sync verificaveis"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.BLOCKED,
        ),
        _mgr(
            "0051_GERENCIAL__aprovar-runner-oficial-wrangler-sem-spawn-eperm",
            "Aprovar runner oficial Wrangler sem spawn EPERM",
            "Separar runner de deploy homologado da sandbox de edicao local.",
            "O runner local historicamente bloqueia node/esbuild/workerd com spawn EPERM.",
            "Runner oficial aprovado com responsabilidade, credencial, dry-run e registro de deploy.",
            ("dados/mcp-publication-gate-mais-humana.json", "ecossistema/MCP-PUBLICATION-GATE-MAIS-HUMANA.md"),
            ("wrangler whoami", "wrangler deploy --dry-run", "wrangler deployments list"),
            ("runner homologado", "deploy dry-run ok", "evidencia de versionamento Cloudflare"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.BLOCKED,
        ),
        _mgr(
            "0052_GERENCIAL__formalizar-nome-canonico-mais-humana-platform-e-aliases",
            "Formalizar nome canonico Mais Humana platform e aliases",
            "Registrar a relacao entre canonico -platform, repo local sem sufixo e alias historico -plataform.",
            "A decisao institucional registrada no roteador aprovou tudo-para-ia-mais-humana-platform como nome canonico.",
            "Nome canonico aprovado, aliases preservados e migracao futura limitada a janela coordenada sem duplicar repositorio.",
            ("README.md", "dados/mcp-publication-gate-mais-humana.json"),
            ("verificar remote", "verificar ownerPlatformId", "verificar referencias centrais"),
            ("decisao institucional registrada", "aliases preservados", "sem repositorio duplicado"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.COMPLETED,
        ),
        _mgr(
            "0053_GERENCIAL__pactuar-docs-catalogonly-ou-response-ready-como-excecao-global",
            "Pactuar Docs catalogOnly ou responseReady como excecao global",
            "Resolver o blocker gerencial recorrente de Docs catalogOnly.",
            "O plano gerencial identifica Docs catalogOnly como impedimento global ou excecao que precisa ser formalizada.",
            "Docs promovido a responseReady minimo ou excecao catalogOnly deliberada registrada no comparador MCP.",
            ("PLANO-GERENCIAL-DO-ECOSSISTEMA.md", "dados/mcp-contratos-humanos.json"),
            ("validar estado Docs", "registrar excecao ou responseReady", "atualizar comparador MCP"),
            ("decisao Docs aprovada", "blocker global eliminado ou formalizado", "ordem tecnica vinculada"),
            role=OrderLifecycleRole.ACTIVE_INPUT,
            status=OrderStatus.BLOCKED,
        ),
    )


def next_output_order_specs() -> tuple[MaterializedOrderSpec, ...]:
    """Return the next continuity orders created by this closeout."""

    return (
        _exec(
            "0042_EXECUTIVA__publicar-catalogo-aceitacao-admin-routes-no-mcps-gateway",
            "Publicar catalogo de aceitacao admin routes no MCPs Gateway",
            "Expor o catalogo gerado de rotas administrativas como capacidade descoberta pelo MCPs Internos.",
            "A homologacao local existe; a publicacao live depende de alteracao/deploy no MCPs Gateway.",
            "Gateway retorna o resumo de aceitacao das rotas via /v1/execute com evidenceId e hashes.",
            ("tudo-para-ia-mcps-internos-plataform/deploy/mcps-gateway", "dados/mcp-admin-route-acceptance-compacto.json"),
            ("testar /v1/execute", "confirmar ok=true", "validar sem segredo bruto"),
            ("tool live responde", "MCP descobre catalogo", "evidencia registrada"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _exec(
            "0043_EXECUTIVA__corrigir-credencial-gitea-e-sincronizar-espelhos-sem-reversao",
            "Corrigir credencial Gitea e sincronizar espelhos sem reversao",
            "Desbloquear fetch/push e comparar hashes dos espelhos com politica anti-reversao.",
            "Schannel/credencial e FETCH_HEAD bloqueiam sincronizacao segura.",
            "Repositorios principais sincronizados ou excecoes por divergencia preservadas com prova.",
            ("dados/repository-mesh-inventory.json", "dados/targeted-sync-audit.json"),
            ("git fetch --all --prune", "git status --short --branch", "git ls-remote"),
            ("credencial funcional", "hashes comparados", "nenhum reset destrutivo"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _exec(
            "0044_EXECUTIVA__registrar-deploy-manual-cloudflare-e-smoke-live-mais-humana",
            "Registrar deploy manual Cloudflare e smoke live Mais Humana",
            "Conciliar a orientacao de deploy manual do usuario com evidencia live repetivel.",
            "O executor nao deve usar plugin como caminho operacional e o roteador informa deploy manual.",
            "Deployment manual registrado por hash/versao e smoke /v1/execute atualizado.",
            ("dados/mcp-publication-gate-mais-humana.json", "dados/mcp-execute-probe-mais-humana.json"),
            ("executar smoke HTTP", "redigir bearer", "registrar deployment observado"),
            ("liveReady true", "deployment id registrado", "sem segredo bruto"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _exec(
            "0045_EXECUTIVA__destravar-sql-central-e-escrita-automatizada-da-plataforma-15",
            "Destravar SQL central e escrita automatizada da plataforma 15",
            "Garantir que scripts da Mais Humana consigam atualizar o dossie central sem fallback manual.",
            "A central historicamente falha com PermissionError ou OperationalError em SQLite.",
            "Escrita central e controle-semantico.sqlite atualizados pelo runtime sem erro.",
            ("controle-semantico.sqlite", "reports", "indexes", "current", "status"),
            ("python -m mais_humana.cli central-materialization", "python -m mais_humana.cli sql-counts"),
            ("SQL central abre para escrita", "arquivos centrais gravados", "status final limpo"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _exec(
            "0046_EXECUTIVA__remover-test-tmp-com-owner-autorizado-ou-excecao-acl",
            "Remover test-tmp com owner autorizado ou excecao ACL",
            "Fechar a higiene operacional que depende de permissao acima da sandbox.",
            "Dois diretorios vazios de .test-tmp continuam inacessiveis por WinError 5.",
            ".test-tmp removido pelo owner do filesystem ou excecao ACL documentada como pendencia externa.",
            (".test-tmp", "dados/workspace-hygiene-report.json"),
            ("python -m mais_humana.cli workspace-hygiene --apply", "verificar path", "registrar WinError 5 se persistir"),
            ("sem node_modules", ".test-tmp ausente ou excecao formal", "report atualizado"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _mgr(
            "0054_GERENCIAL__institucionalizar-catalogo-admin-routes-como-gate-de-release",
            "Institucionalizar catalogo admin routes como gate de release",
            "Fazer do catalogo de rotas administrativas um requisito para release interplataforma.",
            "A regra MCP-only precisa sair do dossie da Mais Humana e virar gate de ecossistema.",
            "Gate aprovado com owner, evidencia, criterios de excecao e rollback.",
            ("ecossistema/MCP-ADMIN-ROUTE-ACCEPTANCE.md", "PLANO-GERENCIAL-DO-ECOSSISTEMA.md"),
            ("avaliar cobertura por plataforma", "aprovar regra MCP-only", "registrar excecoes"),
            ("gate formal aprovado", "bloqueios externos separados", "ordens por plataforma vinculadas"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _mgr(
            "0055_GERENCIAL__governar-sync-automatico-com-precedencia-da-alteracao-valida",
            "Governar sync automatico com precedencia da alteracao valida",
            "Aprovar regra operacional anti-reversao para todos os espelhos.",
            "A ordem permanente exige preservar a alteracao valida mais recente em toda a malha.",
            "Politica de sync documentada com bloqueio destrutivo, evidencias e responsabilidades.",
            ("dados/repository-mesh-reconciliation.json", "dados/repository-mesh-schedulers.json"),
            ("testar scheduler", "comparar hashes", "registrar conflito de precedencia"),
            ("politica aprovada", "logs auditaveis", "bloqueio de reset automatico"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _mgr(
            "0056_GERENCIAL__separar-deploy-manual-e-runner-wrangler-oficial",
            "Separar deploy manual e runner Wrangler oficial",
            "Definir quando deploy manual e aceitavel e quando runner oficial e obrigatorio.",
            "A rodada atual recebeu orientacao de deploy manual pelo usuario e historico de spawn EPERM.",
            "Politica clara para deploy, dry-run, smoke, rollback e evidencia operacional Cloudflare.",
            ("dados/mcp-publication-gate-mais-humana.json", "ecossistema/MCP-PUBLICATION-GATE-MAIS-HUMANA.md"),
            ("validar smoke live", "registrar deployment", "definir owner do runner"),
            ("politica aprovada", "runner ou deploy manual distinguido", "sem uso operacional do plugin"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _mgr(
            "0057_GERENCIAL__governar-migracao-coordenada-do-nome-canonico-platform",
            "Governar migracao coordenada do nome canonico platform",
            "Transformar a decisao institucional ja aprovada em migracao controlada de Git, MCP, Docs e UI.",
            "O roteador aprovou tudo-para-ia-mais-humana-platform como canonico, preservando aliases historicos.",
            "Plano de migracao coordenada com aliases, rollback, hashes e bloqueio de repositorio duplicado.",
            ("README.md", "dados/canonical-identity-graph.json", "dados/mcp-publication-gate-mais-humana.json"),
            ("validar grafo canonico", "comparar remotes", "planejar janela de rename sem reset destrutivo"),
            ("decisao canonica aplicada", "alias preservado", "migracao futura com rollback"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
        _mgr(
            "0058_GERENCIAL__fechar-decisao-docs-response-ready-ou-catalogonly-formal",
            "Fechar decisao Docs responseReady ou catalogOnly formal",
            "Eliminar o blocker Docs da maturidade global por decisao ou implementacao.",
            "Docs aparece repetidamente como catalogOnly pendente no plano gerencial.",
            "Docs com leitura canonica responseReady minima ou excecao formal que nao derruba readiness global.",
            ("PLANO-GERENCIAL-DO-ECOSSISTEMA.md", "dados/mcp-contratos-humanos.json"),
            ("validar comparador MCP", "registrar decisao", "gerar OS tecnica se necessario"),
            ("blocker removido ou formalizado", "owner Docs definido", "proxima execucao clara"),
            role=OrderLifecycleRole.NEXT_OUTPUT,
        ),
    )


def all_order_specs() -> tuple[MaterializedOrderSpec, ...]:
    return active_input_order_specs() + active_managerial_order_specs() + next_output_order_specs()


def _target_path(central_platform_folder: Path, spec: MaterializedOrderSpec) -> Path:
    return central_platform_folder / "orders" / spec.subfolder / spec.filename


def _fallback_order_path(project_root: Path, spec: MaterializedOrderSpec) -> Path:
    return project_root / "os-orientadoras" / "central-materialization-fallback" / spec.subfolder / spec.filename


def _write_order(central_platform_folder: Path, spec: MaterializedOrderSpec, *, overwrite: bool = False) -> MaterializedOrderAction:
    path = _target_path(central_platform_folder, spec)
    if path.exists() and not overwrite:
        return MaterializedOrderAction(spec.order_id, spec.role, str(path), MaterializationStatus.EXISTS)
    try:
        path.parent.mkdir(parents=True, exist_ok=True)
        before = path.exists()
        path.write_text(order_markdown(spec.to_order(), str(central_platform_folder), REAL_REPO), encoding="utf-8")
        return MaterializedOrderAction(
            spec.order_id,
            spec.role,
            str(path),
            MaterializationStatus.UPDATED if before else MaterializationStatus.CREATED,
        )
    except OSError as exc:
        return MaterializedOrderAction(
            spec.order_id,
            spec.role,
            str(path),
            MaterializationStatus.FAILED,
            f"{type(exc).__name__}: {exc}",
        )


def _write_fallback_order(
    project_root: Path,
    central_platform_folder: Path,
    spec: MaterializedOrderSpec,
    *,
    overwrite: bool = True,
) -> MaterializedOrderAction:
    path = _fallback_order_path(project_root, spec)
    if path.exists() and not overwrite:
        return MaterializedOrderAction(spec.order_id, spec.role, str(path), MaterializationStatus.EXISTS)
    try:
        path.parent.mkdir(parents=True, exist_ok=True)
        before = path.exists()
        content = order_markdown(spec.to_order(), str(central_platform_folder), REAL_REPO)
        content = (
            content.rstrip()
            + "\n\n## Espelho operacional de contingencia\n\n"
            + "Esta copia foi gravada no projeto real porque a pasta central ou o SQLite central estavam bloqueados para escrita nesta rodada.\n"
            + "O caminho oficial da ordem continua sendo a central da plataforma 15; este arquivo preserva execucao, rastreabilidade e retomada.\n"
        )
        path.write_text(content, encoding="utf-8")
        return MaterializedOrderAction(
            spec.order_id,
            spec.role,
            str(path),
            MaterializationStatus.UPDATED if before else MaterializationStatus.CREATED,
        )
    except OSError as exc:
        return MaterializedOrderAction(
            spec.order_id,
            spec.role,
            str(path),
            MaterializationStatus.FAILED,
            f"{type(exc).__name__}: {exc}",
        )


def _write_fallback_orders(
    project_root: Path,
    central_platform_folder: Path,
    specs: Sequence[MaterializedOrderSpec],
) -> tuple[MaterializedOrderAction, ...]:
    return tuple(_write_fallback_order(project_root, central_platform_folder, spec) for spec in specs)


def _report_markdown(report: CentralMaterializationReport) -> str:
    lines = [
        "# EXECUTADO - Central Materialization",
        "",
        f"- report_id: `{report.report_id}`",
        f"- generated_at: `{report.generated_at}`",
        f"- status: `{report.status.value}`",
        f"- project_id: `{report.project_id}`",
        f"- project_root: `{report.project_root}`",
        f"- central_platform_folder: `{report.central_platform_folder}`",
        "",
        "## Summary",
        "",
    ]
    lines.extend(f"- {item}" for item in report.summary)
    lines.extend(["", "## Active Input Orders", ""])
    for spec in report.active_input_orders:
        lines.append(f"- `{spec.order_id}` | `{spec.order_type.value}` | `{spec.status.value}` | {spec.title}")
    lines.extend(["", "## Next Output Orders", ""])
    for spec in report.next_output_orders:
        lines.append(f"- `{spec.order_id}` | `{spec.order_type.value}` | `{spec.status.value}` | {spec.title}")
    lines.extend(["", "## Write Actions", ""])
    for action in report.actions:
        lines.append(f"- `{action.order_id}` | `{action.role.value}` | `{action.status.value}` | `{action.path}`")
        if action.error:
            lines.append(f"  - error: `{action.error}`")
    lines.extend(["", "## Semantic SQLite", ""])
    lines.append(f"- attempted: `{report.semantic_write.attempted}`")
    lines.append(f"- ok: `{report.semantic_write.ok}`")
    lines.append(f"- sqlite_path: `{report.semantic_write.sqlite_path}`")
    lines.append(f"- files_count: `{report.semantic_write.files_count}`")
    lines.append(f"- orders_count: `{report.semantic_write.orders_count}`")
    if report.semantic_write.error:
        lines.append(f"- error: `{report.semantic_write.error}`")
    if report.local_semantic_write:
        lines.extend(["", "## SQLite Semantico Local", ""])
        lines.append(f"- attempted: `{report.local_semantic_write.attempted}`")
        lines.append(f"- ok: `{report.local_semantic_write.ok}`")
        lines.append(f"- sqlite_path: `{report.local_semantic_write.sqlite_path}`")
        lines.append(f"- files_count: `{report.local_semantic_write.files_count}`")
        lines.append(f"- orders_count: `{report.local_semantic_write.orders_count}`")
        if report.local_semantic_write.error:
            lines.append(f"- error: `{report.local_semantic_write.error}`")
    if report.fallback_order_files:
        lines.extend(["", "## Ordens Espelhadas no Projeto Real", ""])
        for path in report.fallback_order_files:
            lines.append(f"- `{path}`")
    lines.extend(["", "## Blockers", ""])
    if report.blockers:
        lines.extend(f"- `{item}`" for item in report.blockers)
    else:
        lines.append("- Nenhum blocker de materializacao central.")
    return "\n".join(lines).strip() + "\n"


def _pending_markdown(report: CentralMaterializationReport) -> str:
    lines = [
        "# PENDENCIAS-CODEX - Central Materialization",
        "",
        "## Pendencias reais",
        "",
    ]
    if report.blockers:
        lines.extend(f"- `{item}`" for item in report.blockers)
    else:
        lines.append("- Nenhuma pendencia de materializacao central detectada.")
    lines.extend(
        [
            "",
            "## Observacoes",
            "",
            "- Falha do plugin Cloudflare nao foi tratada como blocker operacional.",
            "- Operacoes Git destrutivas nao foram executadas.",
            "- Deploy Cloudflare permanece vinculado a Wrangler/deploy manual conforme ordem roteadora.",
        ]
    )
    return "\n".join(lines).strip() + "\n"


def _audit_markdown(report: CentralMaterializationReport) -> str:
    created = sum(1 for action in report.actions if action.status == MaterializationStatus.CREATED)
    existing = sum(1 for action in report.actions if action.status == MaterializationStatus.EXISTS)
    failed = sum(1 for action in report.actions if action.status == MaterializationStatus.FAILED)
    lines = [
        "# AUDITORIA-GPT - Central Materialization",
        "",
        "## Confirmado",
        "",
        f"- Ordens avaliadas: `{len(report.actions)}`.",
        f"- Ordens criadas: `{created}`.",
        f"- Ordens ja existentes: `{existing}`.",
        f"- Falhas de escrita: `{failed}`.",
        f"- SQLite central atualizado: `{report.semantic_write.ok}`.",
        f"- Ordens espelhadas no projeto real: `{len(report.fallback_order_files)}`.",
        f"- SQLite semantico local atualizado: `{bool(report.local_semantic_write and report.local_semantic_write.ok)}`.",
        "",
        "## Parcial ou bloqueado",
        "",
    ]
    if report.blockers:
        lines.extend(f"- `{item}`" for item in report.blockers)
    else:
        lines.append("- Nenhum item parcial ou bloqueado na materializacao.")
    lines.extend(
        [
            "",
            "## Leitura gerencial",
            "",
            "- A pasta central agora possui arquivos fisicos para as ordens citadas pela fila.",
            "- Quando a central bloqueia escrita, o projeto real preserva espelhos operacionais das ordens e SQL semantico local.",
            "- As proximas ordens de saida se limitam a publicacao live, credenciais, runner, ACL, nome canonico e Docs.",
        ]
    )
    return "\n".join(lines).strip() + "\n"


def _active_queue_markdown(report: CentralMaterializationReport) -> str:
    lines = [
        "# Fila ativa apos materializacao central - rodada 015",
        "",
        f"Atualizado em `{report.generated_at}`.",
        "",
        "## Ordens de entrada tratadas nesta rodada",
        "",
    ]
    for spec in report.active_input_orders:
        lines.append(f"- `{spec.order_id}` | `{spec.status.value}` | {spec.title}")
    lines.extend(["", "## Ordens executivas de saida ativas", ""])
    for spec in report.next_output_orders:
        if spec.order_type == OrderType.EXECUTIVE:
            lines.append(f"- `{spec.order_id}`")
    lines.extend(["", "## Ordens gerenciais de saida ativas", ""])
    for spec in report.next_output_orders:
        if spec.order_type == OrderType.MANAGERIAL:
            lines.append(f"- `{spec.order_id}`")
    lines.extend(
        [
            "",
            "## Bloqueios preservados",
            "",
        ]
    )
    if report.blockers:
        lines.extend(f"- `{item}`" for item in report.blockers)
    else:
        lines.append("- Nenhum blocker novo na materializacao.")
    return "\n".join(lines).strip() + "\n"


def _state_markdown(report: CentralMaterializationReport) -> str:
    lines = [
        "# Estado atual reconciliado - tudo-para-ia-mais-humana-platform",
        "",
        "## Atualizacao central materialization - 2026-05-02",
        "",
        f"- status: `{report.status.value}`",
        f"- active_input_orders: `{len(report.active_input_orders)}`",
        f"- next_output_orders: `{len(report.next_output_orders)}`",
        f"- semantic_sql_ok: `{report.semantic_write.ok}`",
        f"- local_semantic_sql_ok: `{bool(report.local_semantic_write and report.local_semantic_write.ok)}`",
        f"- fallback_order_files: `{len(report.fallback_order_files)}`",
        f"- project_root: `{report.project_root}`",
        f"- central_platform_folder: `{report.central_platform_folder}`",
        "",
        "A rodada materializou ordens citadas pela fila, gerou o catalogo de aceitacao das rotas administrativas MCP-only, registrou a decisao canonica e preservou como pendencias apenas credencial Git, runner/deploy, ACL local e Docs.",
        "",
        f"Politica canonica: {CANONICAL_COMPATIBILITY_RULE}",
        "",
        "## Saida ativa efetiva",
        "",
    ]
    for spec in report.next_output_orders:
        lines.append(f"- `{spec.order_id}` | `{spec.order_type.value}` | {spec.title}")
    lines.extend(["", "## Bloqueios reais", ""])
    if report.blockers:
        lines.extend(f"- `{item}`" for item in report.blockers)
    else:
        lines.append("- Nenhum blocker novo.")
    return "\n".join(lines).strip() + "\n"


def _orders_index_markdown(report: CentralMaterializationReport) -> str:
    lines = [
        "# Indice de ordens - tudo-para-ia-mais-humana-platform",
        "",
        "## Rodada 015 - materializacao central",
        "",
        "### Tratadas nesta rodada",
        "",
    ]
    for spec in report.active_input_orders:
        lines.append(f"- `{spec.order_id}` | `{spec.order_type.value}` | `{spec.status.value}`")
    lines.extend(["", "### Saida ativa apos materializacao", ""])
    for spec in report.next_output_orders:
        lines.append(f"- `{spec.order_id}` | `{spec.order_type.value}` | `{spec.status.value}`")
    return "\n".join(lines).strip() + "\n"


def _generated_records(report: CentralMaterializationReport, central_platform_folder: Path) -> tuple[GeneratedFile, ...]:
    relation = "0040_EXECUTIVA__materializar-escrita-central-e-sql-semantico-sem-permissionerror"
    paths = (
        ("reports/EXECUTADO__rodada-015-central-materialization-2026-05-02.md", "Relatorio de materializacao central.", "central materialization executed report", "markdown"),
        ("reports/PENDENCIAS-CODEX__rodada-015-central-materialization-2026-05-02.md", "Pendencias da materializacao central.", "central materialization pending report", "markdown"),
        ("audit/AUDITORIA-GPT__rodada-015-central-materialization-2026-05-02.md", "Auditoria da materializacao central.", "central materialization audit", "markdown"),
        ("indexes/INDEX__RODADA015__20260502T0900Z.md", "Indice da materializacao central.", "central materialization index", "markdown"),
        ("indexes/orders-index.md", "Indice reconciliado de ordens.", "orders index", "markdown"),
        ("indexes/ordens-gerenciais-index.md", "Indice reconciliado de ordens gerenciais.", "managerial orders index", "markdown"),
        ("current/active-order-queue.md", "Fila ativa reconciliada.", "active order queue", "markdown"),
        ("current/current-project-state.md", "Estado atual reconciliado.", "current project state", "markdown"),
        ("status/overview.md", "Overview reconciliado.", "status overview", "markdown"),
        ("dados/central-materialization-report.json", "Relatorio estruturado de materializacao central.", "central materialization json", "json"),
    )
    records = [
        GeneratedFile(
            path=str(central_platform_folder / relative),
            description=description,
            function=function,
            file_type=file_type,
            changed_by="mais_humana.central_materialization",
            change_summary="Criado ou atualizado fechamento de materializacao central da rodada 015.",
            relation_to_order=relation,
        )
        for relative, description, function, file_type in paths
    ]
    for action in report.actions:
        records.append(
            GeneratedFile(
                path=action.path,
                description="Arquivo de ordem de servico materializado a partir da fila ativa.",
                function="service order file",
                file_type="markdown",
                changed_by="mais_humana.central_materialization",
                change_summary=f"Materializada ordem {action.order_id} com status {action.status.value}.",
                relation_to_order=action.order_id,
            )
        )
    for path in report.fallback_order_files:
        order_id = Path(path).stem
        records.append(
            GeneratedFile(
                path=path,
                description="Espelho operacional de ordem de servico gravado no projeto real por bloqueio de escrita central.",
                function="fallback service order file",
                file_type="markdown",
                changed_by="mais_humana.central_materialization",
                change_summary=f"Preservada copia de contingencia da ordem {order_id}.",
                relation_to_order=order_id,
            )
        )
    return tuple(records)


def _write_semantic(
    sqlite_path: Path,
    files: Sequence[GeneratedFile],
    specs: Sequence[MaterializedOrderSpec],
) -> SemanticWriteResult:
    try:
        with connect(sqlite_path) as conn:
            upsert_files(conn, files)
            upsert_orders(conn, [spec.to_order() for spec in specs])
            conn.commit()
        return SemanticWriteResult(str(sqlite_path), True, True, len(files), len(specs))
    except (OSError, sqlite3.DatabaseError) as exc:
        return SemanticWriteResult(str(sqlite_path), True, False, len(files), len(specs), f"{type(exc).__name__}: {exc}")


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


def _try_write_artifact(path: Path, content: str) -> tuple[str, str]:
    """Write an artifact and return ``(path, error)`` without aborting."""

    try:
        return _write_artifact(path, content), ""
    except OSError as exc:
        return str(path), f"{type(exc).__name__}: {exc}"


def run_central_materialization(
    *,
    project_root: Path,
    central_platform_folder: Path,
    overwrite: bool = False,
) -> CentralMaterializationReport:
    """Materialize missing central orders, reports, indexes and SQL."""

    active_specs = active_input_order_specs() + active_managerial_order_specs()
    output_specs = next_output_order_specs()
    specs = active_specs + output_specs
    actions = tuple(_write_order(central_platform_folder, spec, overwrite=overwrite) for spec in specs)
    blockers = merge_unique(
        [f"{action.order_id}:{action.error}" for action in actions if action.status == MaterializationStatus.FAILED]
    )
    placeholder_semantic = SemanticWriteResult(str(central_platform_folder / "controle-semantico.sqlite"), False, False, 0, 0)
    report_id = "central-materialization-" + str(abs(hash(json.dumps([action.to_dict() for action in actions], sort_keys=True))))[:12]
    summary = (
        f"Active input orders materialized: {len(active_specs)}.",
        f"Next output orders materialized: {len(output_specs)}.",
        f"Created files: {sum(1 for action in actions if action.status == MaterializationStatus.CREATED)}.",
        f"Existing files: {sum(1 for action in actions if action.status == MaterializationStatus.EXISTS)}.",
        f"Failed writes: {sum(1 for action in actions if action.status == MaterializationStatus.FAILED)}.",
    )
    report = CentralMaterializationReport(
        report_id=report_id,
        generated_at=utc_now(),
        project_id=PROJECT_ID,
        central_platform_folder=str(central_platform_folder),
        project_root=str(project_root),
        active_input_orders=active_specs,
        next_output_orders=output_specs,
        actions=actions,
        semantic_write=placeholder_semantic,
        summary=summary,
        blockers=blockers,
    )
    records = _generated_records(report, central_platform_folder)
    semantic = _write_semantic(central_platform_folder / "controle-semantico.sqlite", records, specs)
    blockers = merge_unique((*blockers, *(("semantic_sql:" + semantic.error,) if semantic.error else ())))
    fallback_actions: tuple[MaterializedOrderAction, ...] = ()
    fallback_files: tuple[str, ...] = ()
    local_semantic: SemanticWriteResult | None = None
    if any(action.status == MaterializationStatus.FAILED for action in actions) or not semantic.ok:
        fallback_actions = _write_fallback_orders(project_root, central_platform_folder, specs)
        fallback_files = tuple(action.path for action in fallback_actions if action.status != MaterializationStatus.FAILED)
        fallback_errors = tuple(f"{action.order_id}:{action.error}" for action in fallback_actions if action.status == MaterializationStatus.FAILED)
        blockers = merge_unique((*blockers, *(f"fallback_order:{item}" for item in fallback_errors)))
    report = CentralMaterializationReport(
        report_id=report.report_id,
        generated_at=report.generated_at,
        project_id=report.project_id,
        central_platform_folder=report.central_platform_folder,
        project_root=report.project_root,
        active_input_orders=report.active_input_orders,
        next_output_orders=report.next_output_orders,
        actions=report.actions,
        semantic_write=semantic,
        summary=report.summary,
        blockers=blockers,
        fallback_order_files=fallback_files,
    )
    if fallback_files:
        local_records = _generated_records(report, central_platform_folder)
        local_semantic = _write_semantic(project_root / "controle-semantico.sqlite", local_records, specs)
        if local_semantic.error:
            blockers = merge_unique((*blockers, "local_semantic_sql:" + local_semantic.error))
        report = CentralMaterializationReport(
            report_id=report.report_id,
            generated_at=report.generated_at,
            project_id=report.project_id,
            central_platform_folder=report.central_platform_folder,
            project_root=report.project_root,
            active_input_orders=report.active_input_orders,
            next_output_orders=report.next_output_orders,
            actions=report.actions,
            semantic_write=report.semantic_write,
            summary=report.summary,
            blockers=blockers,
            fallback_order_files=report.fallback_order_files,
            local_semantic_write=local_semantic,
        )
    artifact_targets = (
        (central_platform_folder / "reports" / "EXECUTADO__rodada-015-central-materialization-2026-05-02.md", _report_markdown(report)),
        (central_platform_folder / "reports" / "PENDENCIAS-CODEX__rodada-015-central-materialization-2026-05-02.md", _pending_markdown(report)),
        (central_platform_folder / "audit" / "AUDITORIA-GPT__rodada-015-central-materialization-2026-05-02.md", _audit_markdown(report)),
        (central_platform_folder / "indexes" / "INDEX__RODADA015__20260502T0900Z.md", _report_markdown(report)),
        (central_platform_folder / "indexes" / "orders-index.md", _orders_index_markdown(report)),
        (central_platform_folder / "indexes" / "ordens-gerenciais-index.md", _orders_index_markdown(report)),
        (central_platform_folder / "current" / "active-order-queue.md", _active_queue_markdown(report)),
        (central_platform_folder / "current" / "current-project-state.md", _state_markdown(report)),
        (central_platform_folder / "status" / "overview.md", _state_markdown(report)),
        (central_platform_folder / "dados" / "central-materialization-report.json", json.dumps(report.to_dict(), ensure_ascii=False, indent=2, sort_keys=True)),
    )
    generated_files: list[str] = []
    artifact_errors: list[str] = []
    for path, content in artifact_targets:
        written_path, error = _try_write_artifact(path, content)
        if error:
            artifact_errors.append(f"{written_path}:{error}")
            continue
        generated_files.append(written_path)
    fallback_targets = (
        (project_root / "dados" / "central-materialization-report.json", json.dumps(report.to_dict(), ensure_ascii=False, indent=2, sort_keys=True)),
        (project_root / "ecossistema" / "CENTRAL-MATERIALIZATION-REPORT.md", _report_markdown(report)),
    )
    for path, content in fallback_targets:
        written_path, error = _try_write_artifact(path, content)
        if error:
            artifact_errors.append(f"{written_path}:{error}")
            continue
        generated_files.append(written_path)
    blockers = merge_unique((*report.blockers, *(f"central_artifact:{item}" for item in artifact_errors)))
    report = CentralMaterializationReport(
        report_id=report.report_id,
        generated_at=report.generated_at,
        project_id=report.project_id,
        central_platform_folder=report.central_platform_folder,
        project_root=report.project_root,
        active_input_orders=report.active_input_orders,
        next_output_orders=report.next_output_orders,
        actions=report.actions,
        semantic_write=report.semantic_write,
        summary=report.summary,
        blockers=blockers,
        generated_files=tuple((*generated_files, *report.fallback_order_files)),
        fallback_order_files=report.fallback_order_files,
        local_semantic_write=report.local_semantic_write,
    )
    for path, _content in fallback_targets:
        if path.exists():
            path.write_text(json.dumps(report.to_dict(), ensure_ascii=False, indent=2, sort_keys=True) if path.suffix == ".json" else _report_markdown(report), encoding="utf-8")
    return report
