"""Human-readable narratives generated from scans and matrix cells."""

from __future__ import annotations

from typing import Sequence

from .catalog import HUMAN_PROFILES, HUMAN_NEEDS, PROFILE_BY_ID
from .models import MatrixCell, PlatformHumanReport, PlatformScan, Recommendation, score_label


def sentence_list(items: Sequence[str], fallback: str = "nao informado") -> str:
    values = [item.strip() for item in items if item and item.strip()]
    if not values:
        return fallback
    if len(values) == 1:
        return values[0]
    return ", ".join(values[:-1]) + " e " + values[-1]


def platform_intro(scan: PlatformScan) -> str:
    if not scan.exists:
        return (
            f"{scan.platform.title} ainda nao possui repositorio local analisavel. "
            "Para pessoas reais, isso significa ausencia de prova operacional na base desta plataforma."
        )
    git_state = "com Git local" if scan.git_present else "sem Git local"
    return (
        f"{scan.platform.title} existe em {scan.repo_path}, {git_state}, "
        f"com {scan.code_lines} linhas de codigo analisaveis e {len(scan.evidence)} evidencias coletadas."
    )


def profile_section(cell: MatrixCell) -> tuple[str, ...]:
    profile = PROFILE_BY_ID[cell.profile_id]
    lines = [
        f"Perfil: {profile.name}",
        f"Score: {cell.score} ({score_label(cell.score)}), maturidade: {cell.maturity.value}.",
        f"Leitura: {cell.explanation}",
        "Forcas: " + sentence_list(cell.strengths),
        "Lacunas: " + sentence_list(cell.gaps),
    ]
    if cell.evidence_refs:
        lines.append("Evidencias: " + sentence_list(cell.evidence_refs[:5]))
    return tuple(lines)


def current_state_paragraph(report: PlatformHumanReport) -> str:
    return (
        "Estado atual humano: "
        + sentence_list(report.current_state, "a plataforma precisa de evidencias iniciais")
        + "."
    )


def future_state_paragraph(report: PlatformHumanReport) -> str:
    return "Estado futuro esperado: " + sentence_list(report.future_state) + "."


def missing_state_paragraph(report: PlatformHumanReport) -> str:
    return "O que ainda falta para atender melhor: " + sentence_list(report.missing_for_humans) + "."


def recommendation_paragraph(recommendation: Recommendation) -> str:
    categories = ", ".join(category.value for category in recommendation.categories)
    validations = sentence_list(recommendation.validation_steps, "validacao a definir")
    return (
        f"{recommendation.title}. Motivo: {recommendation.reason} "
        f"Impacto esperado: {recommendation.expected_impact} "
        f"Categorias: {categories}. Validacao: {validations}."
    )


def platform_report_lines(report: PlatformHumanReport) -> list[str]:
    lines: list[str] = []
    lines.append(report.platform.title)
    lines.append(report.platform.mission)
    lines.append(platform_intro(report.scan))
    lines.append(report.summary)
    lines.append(current_state_paragraph(report))
    lines.append(future_state_paragraph(report))
    lines.append(missing_state_paragraph(report))
    lines.append("Perfis humanos")
    for cell in sorted(report.cells, key=lambda item: item.profile_id):
        lines.extend(profile_section(cell))
    lines.append("Recomendacoes")
    for recommendation in report.recommendations[:10]:
        lines.append(recommendation_paragraph(recommendation))
    if report.scan.warnings:
        lines.append("Avisos operacionais: " + sentence_list(report.scan.warnings))
    return lines


def ecosystem_summary_lines(reports: Sequence[PlatformHumanReport]) -> list[str]:
    total_code = sum(report.scan.code_lines for report in reports)
    total_evidence = sum(len(report.scan.evidence) for report in reports)
    average = round(sum(report.average_score for report in reports) / len(reports)) if reports else 0
    lines = [
        "Relatorio Geral do Ecossistema Mais Humano",
        (
            f"Foram avaliadas {len(reports)} plataformas, com {total_code} linhas de codigo "
            f"e {total_evidence} evidencias locais."
        ),
        f"Score medio humano do ecossistema: {average}.",
        (
            "A pergunta central desta plataforma e simples: quem e atendido, como e atendido, "
            "o que ja funciona hoje e o que precisa virar ordem de servico para servir melhor pessoas reais."
        ),
    ]
    lines.append("Leitura por necessidade humana")
    for need in HUMAN_NEEDS:
        related = [
            report.platform.platform_id
            for report in reports
            if need.category in report.platform.primary_categories
        ]
        lines.append(
            f"{need.title}: plataformas relacionadas {sentence_list(related, 'nenhuma principal')}. "
            f"Risco se faltar: {need.risk_if_missing}"
        )
    lines.append("Plataformas com menor score medio")
    for report in sorted(reports, key=lambda item: item.average_score)[:8]:
        lines.append(
            f"{report.platform.title}: score {report.average_score}; "
            f"lacunas principais: {sentence_list(report.missing_for_humans[:3])}."
        )
    lines.append("Plataformas com maior prontidao humana")
    for report in sorted(reports, key=lambda item: item.average_score, reverse=True)[:8]:
        lines.append(
            f"{report.platform.title}: score {report.average_score}; "
            f"forcas: {sentence_list(report.current_state[:3])}."
        )
    return lines


def markdown_table(headers: Sequence[str], rows: Sequence[Sequence[str]]) -> str:
    output = ["| " + " | ".join(headers) + " |"]
    output.append("| " + " | ".join("---" for _ in headers) + " |")
    for row in rows:
        output.append("| " + " | ".join(str(value).replace("|", "/") for value in row) + " |")
    return "\n".join(output)


def platform_markdown(report: PlatformHumanReport) -> str:
    lines = [f"# {report.platform.title}", "", report.platform.mission, ""]
    lines.append("## Sintese")
    lines.append("")
    lines.append(report.summary)
    lines.append("")
    lines.append(current_state_paragraph(report))
    lines.append("")
    lines.append(future_state_paragraph(report))
    lines.append("")
    lines.append(missing_state_paragraph(report))
    lines.append("")
    lines.append("## Matriz por perfil")
    rows = []
    for cell in sorted(report.cells, key=lambda item: item.profile_id):
        profile = PROFILE_BY_ID[cell.profile_id]
        rows.append([profile.name, str(cell.score), cell.maturity.value, cell.explanation])
    lines.append(markdown_table(["Perfil", "Score", "Maturidade", "Leitura"], rows))
    lines.append("")
    lines.append("## Recomendacoes")
    lines.append("")
    for recommendation in report.recommendations:
        lines.append(f"- {recommendation_paragraph(recommendation)}")
    if report.scan.warnings:
        lines.append("")
        lines.append("## Avisos")
        lines.extend(f"- {warning}" for warning in report.scan.warnings)
    return "\n".join(lines).strip() + "\n"


def ecosystem_markdown(reports: Sequence[PlatformHumanReport]) -> str:
    lines = ["# Relatorio Geral do Ecossistema Mais Humano", ""]
    lines.extend(ecosystem_summary_lines(reports)[1:])
    lines.append("")
    lines.append("## Matriz plataforma x perfil")
    rows = []
    for report in sorted(reports, key=lambda item: item.platform.platform_id):
        strongest = sorted(report.cells, key=lambda item: item.score, reverse=True)[:3]
        weakest = sorted(report.cells, key=lambda item: item.score)[:3]
        rows.append(
            [
                report.platform.platform_id,
                str(report.average_score),
                sentence_list([PROFILE_BY_ID[cell.profile_id].name for cell in strongest]),
                sentence_list([PROFILE_BY_ID[cell.profile_id].name for cell in weakest]),
            ]
        )
    lines.append(markdown_table(["Plataforma", "Score", "Mais atendidos", "Mais frageis"], rows))
    lines.append("")
    lines.append("## Perfis considerados")
    for profile in HUMAN_PROFILES:
        lines.append(f"- {profile.name}: {profile.description}")
    return "\n".join(lines).strip() + "\n"

