"""Output formatters for CLI reporting."""

from __future__ import annotations

import html

from agentmd.drift import DriftReport, FileDriftReport, SectionStaleDetail

MARKDOWN_HEADER = "## 🔍 agentmd Context Drift Report"
MARKDOWN_FOOTER = "Generated by [agentmd](https://github.com/mikiships/agentmd)"


def render_markdown_report(report: DriftReport) -> str:
    """Render drift report as markdown intended for PR comments."""
    lines: list[str] = [
        MARKDOWN_HEADER,
        "",
        _summary_line(report),
        "",
        "| Section | Status | Detail |",
        "| --- | --- | --- |",
    ]

    rows = _collect_rows(report)
    if rows:
        for section, status, detail in rows:
            lines.append(f"| {_escape_table(section)} | {status} | {_escape_table(detail)} |")
    else:
        lines.append("| (none) | fresh | No sections found for comparison |")

    detail_blocks = _render_detail_blocks(report.files)
    if detail_blocks:
        lines.append("")
        lines.extend(detail_blocks)

    lines.extend(["", MARKDOWN_FOOTER])
    return "\n".join(lines)


def _summary_line(report: DriftReport) -> str:
    if not report.has_drift:
        return "✅ Context files are fresh"

    drifted_files = [item for item in report.files if item.has_drift]
    section_count = sum(
        len(item.sections_added) + len(item.sections_removed) + len(item.sections_changed)
        for item in drifted_files
    )

    if len(drifted_files) == 1:
        target = drifted_files[0].file
        return f"⚠️ {section_count} {_plural(section_count, 'section')} drifted in {target}"

    return (
        f"⚠️ {section_count} {_plural(section_count, 'section')} drifted across "
        f"{len(drifted_files)} {_plural(len(drifted_files), 'file')}"
    )


def _collect_rows(report: DriftReport) -> list[tuple[str, str, str]]:
    rows: list[tuple[str, str, str]] = []
    for file_report in report.files:
        rows.extend(_rows_for_file(file_report))
    return rows


def _rows_for_file(file_report: FileDriftReport) -> list[tuple[str, str, str]]:
    rows: list[tuple[str, str, str]] = []

    for section in file_report.sections_changed:
        rows.append(
            (
                _section_label(file_report.file, section),
                "stale",
                "Section content differs from generated output",
            )
        )

    for section in file_report.sections_removed:
        rows.append(
            (
                _section_label(file_report.file, section),
                "missing",
                "Section exists in the current file but not in generated output",
            )
        )

    for section in file_report.sections_added:
        rows.append(
            (
                _section_label(file_report.file, section),
                "new",
                "Section exists in generated output but not in the current file",
            )
        )

    for section in file_report.sections_fresh:
        rows.append(
            (
                _section_label(file_report.file, section),
                "fresh",
                "Section matches generated output",
            )
        )

    if rows:
        return rows

    status = "fresh" if not file_report.has_drift else file_report.status
    detail = "No section headings were found; compared as full document"
    return [(_section_label(file_report.file, "full_document"), status, detail)]


def _render_detail_blocks(files: list[FileDriftReport]) -> list[str]:
    blocks: list[str] = []
    for file_report in files:
        if not file_report.has_drift:
            continue

        for detail in file_report.stale_details:
            diff_text = detail.diff.rstrip() or "(no diff available)"
            status = _status_label(detail)
            summary = html.escape(f"{file_report.file} · {detail.section} ({status})")
            blocks.extend(
                [
                    "<details>",
                    f"<summary>{summary}</summary>",
                    "",
                    "```diff",
                    diff_text,
                    "```",
                    "</details>",
                    "",
                ]
            )

    if blocks and not blocks[-1].strip():
        blocks.pop()

    return blocks


def _status_label(detail: SectionStaleDetail) -> str:
    if detail.status == "added":
        return "new"
    if detail.status == "removed":
        return "missing"
    return "stale"


def _section_label(file_name: str, section: str) -> str:
    return f"{file_name} :: {section}"


def _escape_table(value: str) -> str:
    return value.replace("|", "\\|").replace("\n", "<br>")


def _plural(value: int, singular: str) -> str:
    return singular if value == 1 else f"{singular}s"
