"""Service order generation for the human-centered platform."""

from __future__ import annotations

from pathlib import Path
import re
from typing import Sequence

from .models import OrderStatus, OrderType, PlatformHumanReport, Recommendation, ServiceOrder, incrementing_id, slugify


def order_from_recommendation(
    recommendation: Recommendation,
    index: int,
    order_type: OrderType,
    project_id: str = "tudo-para-ia-mais-humana",
) -> ServiceOrder:
    title = recommendation.title
    return ServiceOrder(
        order_id=incrementing_id("EXECUTIVA" if order_type == OrderType.EXECUTIVE else "GERENCIAL", index, title),
        order_type=order_type,
        project_id=project_id,
        title=title,
        purpose=(
            "Transformar uma lacuna detectada pela matriz humana em continuidade operacional "
            "validavel, registrada e vinculada a evidencias."
        ),
        object_scope=(
            f"Plataforma relacionada: {recommendation.platform_id}. "
            "Areas afetadas: " + ", ".join(recommendation.affected_paths or ("a identificar durante execucao",))
        ),
        reason=recommendation.reason,
        expected_result=recommendation.expected_impact,
        affected_paths=recommendation.affected_paths,
        validations=recommendation.validation_steps,
        ready_criteria=(
            "lacuna humana reavaliada",
            "evidencia registrada",
            "relatorio ou matriz atualizado",
            "SQL semantico atualizado",
        ),
        status=OrderStatus.PLANNED,
        priority="alta" if recommendation.priority >= 85 else "media",
    )


def select_recommendations(
    recommendations: Sequence[Recommendation],
    order_type: OrderType,
    limit: int = 5,
) -> tuple[Recommendation, ...]:
    filtered = [item for item in recommendations if item.suggested_order_type == order_type]
    if len(filtered) < limit:
        filtered.extend(item for item in recommendations if item.suggested_order_type != order_type)
    selected: list[Recommendation] = []
    seen: set[str] = set()
    for item in sorted(filtered, key=lambda rec: (-rec.priority, rec.platform_id, rec.title)):
        key = item.recommendation_id
        if key in seen:
            continue
        seen.add(key)
        selected.append(item)
        if len(selected) >= limit:
            break
    return tuple(selected)


def build_exit_orders(recommendations: Sequence[Recommendation], project_id: str = "tudo-para-ia-mais-humana") -> tuple[ServiceOrder, ...]:
    executive = select_recommendations(recommendations, OrderType.EXECUTIVE, limit=5)
    managerial = select_recommendations(recommendations, OrderType.MANAGERIAL, limit=5)
    orders: list[ServiceOrder] = []
    for index, recommendation in enumerate(executive, start=1):
        orders.append(order_from_recommendation(recommendation, index, OrderType.EXECUTIVE, project_id))
    for index, recommendation in enumerate(managerial, start=1):
        orders.append(order_from_recommendation(recommendation, index, OrderType.MANAGERIAL, project_id))
    return tuple(orders)


def order_markdown(order: ServiceOrder, platform_folder: str, real_repo: str) -> str:
    lines = [
        f"# ORDEM DE SERVICO: {order.order_id}",
        "",
        "Template oficial:",
        "",
        "`G:/_codex-git/nucleo-gestao-operacional/templates/ordem-de-servico.md`",
        "",
        "## Finalidade da ordem de servico",
        "",
        order.purpose,
        "",
        "## Objeto da ordem de servico",
        "",
        order.object_scope,
        "",
        "## Motivo da criacao da ordem de servico",
        "",
        order.reason,
        "",
        "## Resultado esperado da execucao",
        "",
        order.expected_result,
        "",
        "## Tipo da ordem",
        "",
        f"`{order.order_type.value.upper()}`",
        "",
        "## Identificacao",
        "",
        f"- order_id: `{order.order_id}`",
        f"- tipo: `{order.order_type.value}`",
        f"- project_id: `{order.project_id}`",
        f"- repo_name: `{real_repo}`",
        f"- status: `{order.status.value}`",
        f"- prioridade: `{order.priority}`",
        "",
        "## Caminhos",
        "",
        "Pasta da plataforma:",
        "",
        f"`{platform_folder}`",
        "",
        "Projeto real:",
        "",
        f"`G:/_codex-git/{real_repo}`",
        "",
        "SQLite semantico:",
        "",
        f"`{platform_folder}/controle-semantico.sqlite`",
        "",
        "## Arquivos e areas afetadas",
        "",
    ]
    for path in order.affected_paths or ("a identificar durante a execucao",):
        lines.append(f"- `{path}`")
    lines.extend(["", "## Validacoes", ""])
    for validation in order.validations or ("validacao a definir durante execucao",):
        lines.append(f"- {validation}")
    lines.extend(["", "## Criterio de pronto", ""])
    for criterion in order.ready_criteria:
        lines.append(f"- {criterion}")
    lines.extend(
        [
            "",
            "## Fechamento obrigatorio",
            "",
            "- registrar EXECUTADO;",
            "- registrar PENDENCIAS reais;",
            "- atualizar SQL semantico;",
            "- registrar funcao dos arquivos criados ou alterados;",
            "- fazer commit e push quando aplicavel;",
            "- informar hashes finais.",
            "",
        ]
    )
    return "\n".join(lines)


def write_orders(
    orders: Sequence[ServiceOrder],
    platform_folder: Path,
    real_repo: str = "tudo-para-ia-mais-humana",
) -> tuple[Path, ...]:
    written: list[Path] = []
    next_number: dict[str, int] = {}
    used_existing_paths: set[Path] = set()
    max_attempts_per_order = 200
    for order in orders:
        subfolder = "executivas" if order.order_type == OrderType.EXECUTIVE else "gerenciais"
        target_dir = platform_folder / "orders" / subfolder
        target_dir.mkdir(parents=True, exist_ok=True)
        if subfolder not in next_number:
            numbers: list[int] = []
            for existing in target_dir.glob("*.md"):
                match = re.match(r"^(\d{4})_", existing.name)
                if match:
                    numbers.append(int(match.group(1)))
            next_number[subfolder] = (max(numbers) + 1) if numbers else 1
        prefix = "EXECUTIVA" if order.order_type == OrderType.EXECUTIVE else "GERENCIAL"
        order_slug = slugify(order.title)
        existing_same_order = [
            path for path in sorted(target_dir.glob(f"*_{prefix}__{order_slug}.md"), reverse=True) if path not in used_existing_paths
        ]
        if existing_same_order:
            path = existing_same_order[0]
            used_existing_paths.add(path)
            order.order_id = path.stem
            try:
                path.write_text(order_markdown(order, str(platform_folder), real_repo), encoding="utf-8")
            except PermissionError:
                # The central can be dirty or temporarily locked by a previous
                # round.  Reusing the existing active order is safer than
                # creating hundreds of duplicate continuations with the same
                # semantic title.
                written.append(path)
                continue
            written.append(path)
            continue
        last_error: PermissionError | None = None
        for _attempt in range(max_attempts_per_order):
            order.order_id = incrementing_id(prefix, next_number[subfolder], order.title)
            next_number[subfolder] += 1
            filename = order.order_id
            if not filename.endswith(".md"):
                filename += ".md"
            path = target_dir / filename
            if path.exists():
                continue
            try:
                path.write_text(order_markdown(order, str(platform_folder), real_repo), encoding="utf-8")
            except PermissionError as exc:
                last_error = exc
                continue
            written.append(path)
            break
        else:
            detail = f"Nao foi possivel gravar ordem em {target_dir} apos {max_attempts_per_order} tentativas."
            if last_error is not None:
                detail = f"{detail} Ultimo erro: {last_error}"
            raise PermissionError(detail)
    return tuple(written)


def executed_order_markdown(reports: Sequence[PlatformHumanReport], orders: Sequence[ServiceOrder]) -> str:
    total_code = sum(report.scan.code_lines for report in reports)
    avg = round(sum(report.average_score for report in reports) / len(reports)) if reports else 0
    lines = [
        "# EXECUTADO - Fundacao da plataforma tudo-para-ia-mais-humana",
        "",
        "## Sintese",
        "",
        "A rodada criou uma base operacional inicial para traduzir o estado tecnico do ecossistema em leitura humana.",
        "",
        f"- plataformas avaliadas: {len(reports)}",
        f"- linhas de codigo analisadas: {total_code}",
        f"- score medio humano: {avg}",
        f"- ordens de saida criadas: {len(orders)}",
        "",
        "## Arquivos e capacidades criadas",
        "",
        "- pacote Python `mais_humana` com scanner, matriz, DOCX, SVG, SQLite e gerador de OS;",
        "- relatorios DOCX e Markdown por plataforma;",
        "- relatorio geral do ecossistema;",
        "- graficos SVG de maturidade e matriz;",
        "- dados JSON auditaveis;",
        "- SQL semantico atualizado;",
        "- ordens executivas e gerenciais de saida.",
        "",
        "## Plataformas avaliadas",
        "",
    ]
    for report in sorted(reports, key=lambda item: item.platform.platform_id):
        lines.append(f"- {report.platform.platform_id}: score {report.average_score}, codigo {report.scan.code_lines} linhas")
    return "\n".join(lines) + "\n"


def pending_markdown(reports: Sequence[PlatformHumanReport], push_status: str | None = None) -> str:
    lines = ["# PENDENCIAS-CODEX - tudo-para-ia-mais-humana", ""]
    lines.append("## Pendencias reais")
    lines.append("")
    if push_status:
        lines.append(f"- Sincronizacao Git remota: {push_status}")
    for report in sorted(reports, key=lambda item: item.platform.platform_id):
        for warning in report.scan.warnings:
            lines.append(f"- {report.platform.platform_id}: {warning}")
    if len(lines) == 4:
        lines.append("- Nenhuma pendencia material detectada nesta rodada.")
    lines.append("")
    lines.append("## Proximo passo")
    lines.append("")
    lines.append("Executar as ordens de saida criadas e comparar novos scores contra os dados desta rodada.")
    return "\n".join(lines) + "\n"


def audit_markdown(reports: Sequence[PlatformHumanReport], orders: Sequence[ServiceOrder]) -> str:
    lines = [
        "# AUDITORIA-GPT - Fundacao tudo-para-ia-mais-humana",
        "",
        "## Confirmado",
        "",
        "- Repositorio real estruturado como plataforma propria.",
        "- Base tecnica criada para gerar relatorios humanos e matrizes.",
        "- Ordens de saida geradas a partir de recomendacoes reais.",
        "- SQL semantico atualizado por camada compacta.",
        "",
        "## Parcial",
        "",
        "- Push remoto depende de credencial Git disponivel no ambiente.",
        "- Relatorios DOCX iniciais foram gerados por escritor minimalista sem dependencia externa.",
        "",
        "## Amostra de scores",
        "",
    ]
    for report in sorted(reports, key=lambda item: item.average_score)[:8]:
        lines.append(f"- {report.platform.platform_id}: {report.average_score}")
    lines.extend(["", "## Ordens criadas", ""])
    for order in orders:
        lines.append(f"- {order.order_id}: {order.title}")
    return "\n".join(lines) + "\n"
