"""Human readiness registry derived from platform and governance reports."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Sequence

from .catalog import HUMAN_PROFILES, PLATFORM_BY_ID
from .governance_models import EcosystemGovernancePortfolio, GovernanceDomain, GovernanceStatus
from .models import MatrixCell, PlatformHumanReport, as_plain_data, merge_unique


@dataclass(slots=True)
class ReadinessRegistryEntry:
    entry_id: str
    platform_id: str
    profile_id: str
    platform_title: str
    profile_name: str
    human_score: int
    governance_score: int
    status: str
    strengths: tuple[str, ...]
    gaps: tuple[str, ...]
    evidence_refs: tuple[str, ...]
    recommended_action: str

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


@dataclass(slots=True)
class ReadinessRegistry:
    project_id: str
    entries: tuple[ReadinessRegistryEntry, ...]
    platform_summary: tuple[tuple[str, int, int, str], ...]
    profile_summary: tuple[tuple[str, int, int], ...]
    domain_gaps: tuple[tuple[str, str, int], ...]

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

    @property
    def weak_entries(self) -> tuple[ReadinessRegistryEntry, ...]:
        return tuple(entry for entry in self.entries if entry.human_score < 60 or entry.status in {"bloqueado", "critico"})


def cell_by_platform_profile(reports: Sequence[PlatformHumanReport]) -> dict[tuple[str, str], MatrixCell]:
    cells: dict[tuple[str, str], MatrixCell] = {}
    for report in reports:
        for cell in report.cells:
            cells[(cell.platform_id, cell.profile_id)] = cell
    return cells


def status_for_entry(human_score: int, governance_score: int, card_status: str) -> str:
    if card_status in {"critico", "bloqueado"}:
        return card_status
    if human_score >= 85 and governance_score >= 80:
        return "pronto"
    if human_score >= 70 and governance_score >= 65:
        return "util"
    if human_score >= 50 or governance_score >= 50:
        return "atencao"
    return "fragil"


def action_for_entry(cell: MatrixCell | None, card_status: str, domain_hint: str) -> str:
    if card_status in {"critico", "bloqueado"}:
        return "resolver blockers de governanca antes de promover experiencia humana"
    if cell is None:
        return "gerar matriz humana para esta combinacao"
    if cell.score < 50:
        return "criar tela, relatorio ou comando humano para o perfil"
    if cell.gaps:
        return f"fechar lacuna principal: {cell.gaps[0]}"
    return f"manter regressao e evidencia no dominio {domain_hint}"


def build_registry_entries(reports: Sequence[PlatformHumanReport], portfolio: EcosystemGovernancePortfolio) -> tuple[ReadinessRegistryEntry, ...]:
    cells = cell_by_platform_profile(reports)
    entries: list[ReadinessRegistryEntry] = []
    for report in reports:
        card = portfolio.card_for(report.platform.platform_id)
        governance_score = card.governance_score if card else 0
        card_status = card.status_label if card else "desconhecido"
        domain_hint = report.platform.primary_categories[0].value if report.platform.primary_categories else "governance"
        for profile in HUMAN_PROFILES:
            cell = cells.get((report.platform.platform_id, profile.profile_id))
            human_score = cell.score if cell else 0
            status = status_for_entry(human_score, governance_score, card_status)
            entries.append(
                ReadinessRegistryEntry(
                    entry_id=f"{report.platform.platform_id}.{profile.profile_id}",
                    platform_id=report.platform.platform_id,
                    profile_id=profile.profile_id,
                    platform_title=report.platform.title,
                    profile_name=profile.name,
                    human_score=human_score,
                    governance_score=governance_score,
                    status=status,
                    strengths=cell.strengths if cell else (),
                    gaps=cell.gaps if cell else ("matriz nao gerada",),
                    evidence_refs=cell.evidence_refs if cell else (),
                    recommended_action=action_for_entry(cell, card_status, domain_hint),
                )
            )
    return tuple(entries)


def build_platform_summary(entries: Sequence[ReadinessRegistryEntry]) -> tuple[tuple[str, int, int, str], ...]:
    rows: list[tuple[str, int, int, str]] = []
    platforms = sorted({entry.platform_id for entry in entries})
    for platform_id in platforms:
        platform_entries = [entry for entry in entries if entry.platform_id == platform_id]
        human_avg = round(sum(entry.human_score for entry in platform_entries) / len(platform_entries)) if platform_entries else 0
        gov_avg = round(sum(entry.governance_score for entry in platform_entries) / len(platform_entries)) if platform_entries else 0
        weak = sum(1 for entry in platform_entries if entry.status in {"fragil", "atencao", "bloqueado", "critico"})
        status = "pronto" if weak == 0 else "atencao" if weak < len(platform_entries) else "critico"
        rows.append((platform_id, human_avg, gov_avg, status))
    return tuple(rows)


def build_profile_summary(entries: Sequence[ReadinessRegistryEntry]) -> tuple[tuple[str, int, int], ...]:
    rows: list[tuple[str, int, int]] = []
    profiles = sorted({entry.profile_id for entry in entries})
    for profile_id in profiles:
        profile_entries = [entry for entry in entries if entry.profile_id == profile_id]
        avg = round(sum(entry.human_score for entry in profile_entries) / len(profile_entries)) if profile_entries else 0
        weak = sum(1 for entry in profile_entries if entry.status in {"fragil", "atencao", "bloqueado", "critico"})
        rows.append((profile_id, avg, weak))
    return tuple(rows)


def build_domain_gaps(portfolio: EcosystemGovernancePortfolio) -> tuple[tuple[str, str, int], ...]:
    rows: list[tuple[str, str, int]] = []
    for card in portfolio.cards:
        counts: dict[str, int] = {}
        for check in card.checks:
            if check.status in {GovernanceStatus.ATTENTION, GovernanceStatus.FAIL, GovernanceStatus.BLOCKED}:
                counts[check.domain.value] = counts.get(check.domain.value, 0) + 1
        for domain, count in sorted(counts.items()):
            rows.append((card.platform_id, domain, count))
    return tuple(rows)


def build_readiness_registry(reports: Sequence[PlatformHumanReport], portfolio: EcosystemGovernancePortfolio) -> ReadinessRegistry:
    entries = build_registry_entries(reports, portfolio)
    return ReadinessRegistry(
        project_id="tudo-para-ia-mais-humana",
        entries=entries,
        platform_summary=build_platform_summary(entries),
        profile_summary=build_profile_summary(entries),
        domain_gaps=build_domain_gaps(portfolio),
    )


def registry_markdown(registry: ReadinessRegistry) -> str:
    lines = [
        "# Registro de prontidao humana",
        "",
        f"- project_id: `{registry.project_id}`",
        f"- entradas: `{len(registry.entries)}`",
        f"- entradas frageis: `{len(registry.weak_entries)}`",
        "",
        "## Plataformas",
        "",
    ]
    for platform_id, human_avg, gov_avg, status in registry.platform_summary:
        title = PLATFORM_BY_ID[platform_id].title if platform_id in PLATFORM_BY_ID else platform_id
        lines.append(f"- `{platform_id}` {title}: humano `{human_avg}`, governanca `{gov_avg}`, status `{status}`")
    lines.extend(["", "## Perfis", ""])
    for profile_id, avg, weak in registry.profile_summary:
        lines.append(f"- `{profile_id}`: score medio `{avg}`, plataformas com atencao `{weak}`")
    lines.extend(["", "## Lacunas por dominio", ""])
    for platform_id, domain, count in registry.domain_gaps:
        lines.append(f"- `{platform_id}` / `{domain}`: `{count}` checks em atencao/falha/bloqueio")
    lines.extend(["", "## Entradas mais frageis", ""])
    for entry in sorted(registry.weak_entries, key=lambda item: (item.human_score, item.governance_score, item.platform_id, item.profile_id))[:40]:
        lines.append(
            f"- `{entry.platform_id}` -> `{entry.profile_id}`: status `{entry.status}`, "
            f"humano `{entry.human_score}`, governanca `{entry.governance_score}`; acao: {entry.recommended_action}"
        )
    return "\n".join(lines).strip() + "\n"


def registry_rows(registry: ReadinessRegistry) -> list[list[str]]:
    rows = [["platform", "profile", "human_score", "governance_score", "status", "action"]]
    for entry in sorted(registry.entries, key=lambda item: (item.platform_id, item.profile_id)):
        rows.append(
            [
                entry.platform_id,
                entry.profile_id,
                str(entry.human_score),
                str(entry.governance_score),
                entry.status,
                entry.recommended_action,
            ]
        )
    return rows


def registry_gap_actions(registry: ReadinessRegistry, limit: int = 20) -> tuple[str, ...]:
    actions: list[str] = []
    for entry in sorted(registry.weak_entries, key=lambda item: (item.human_score, item.platform_id, item.profile_id)):
        actions.append(f"{entry.platform_id}/{entry.profile_id}: {entry.recommended_action}")
        if len(actions) >= limit:
            break
    return merge_unique(actions)
