"""Rendering helpers for ``agents project context set`` output."""

from __future__ import annotations

from typing import Any

from rich.panel import Panel

from cleveragents.domain.models.core.context_policy import (
    ContextView,
    ProjectContextPolicy,
)

__all__ = [
    "build_context_set_payload",
    "render_context_set_plain",
    "render_context_set_rich",
]


def _format_size(value: int | None) -> str:
    """Render byte sizes using binary units with whole numbers."""

    if value is None:
        return "(no limit)"

    units = [
        ("TB", 1024**4),
        ("GB", 1024**3),
        ("MB", 1024**2),
        ("KB", 1024),
    ]
    for unit, factor in units:
        if value % factor == 0:
            return f"{value // factor} {unit}"
    return f"{value} bytes"


def _format_inline_list(values: list[str], empty_placeholder: str) -> str:
    """Join a list into a comma-separated string with a placeholder for empty."""

    return ", ".join(values) if values else empty_placeholder


def _is_view_default(view: ContextView) -> bool:
    """Determine whether a view matches the default configuration."""

    default_view = ContextView()
    return view.model_dump(mode="json") == default_view.model_dump(mode="json")


def _view_status(policy: ProjectContextPolicy, phase: str) -> str:
    """Summarise configuration state for a phase view."""

    if phase == "default":
        return "(unset)" if _is_view_default(policy.default_view) else "configured"

    view_obj = getattr(policy, f"{phase}_view")
    return "(default)" if view_obj is None else "configured"


def build_context_set_payload(
    project: str,
    view: str,
    policy: ProjectContextPolicy,
    acms: dict[str, Any],
    *,
    default_limits: dict[str, int | None],
) -> dict[str, Any]:
    """Construct the structured payload for the context-set command."""

    resolved_view = policy.resolve_view(view)
    context_policy = {
        "project": project,
        "view": view,
        "include_resources": resolved_view.include_resources,
        "exclude_resources": resolved_view.exclude_resources,
        "include_paths": resolved_view.include_paths,
        "exclude_paths": resolved_view.exclude_paths,
    }

    limits = {
        "hot_max_tokens": acms.get(
            "hot_max_tokens", default_limits.get("hot_max_tokens")
        ),
        "warm_max_decisions": acms.get(
            "warm_max_decisions", default_limits.get("warm_max_decisions")
        ),
        "cold_max_decisions": acms.get(
            "cold_max_decisions", default_limits.get("cold_max_decisions")
        ),
        "query_limit": acms.get("query_limit", default_limits.get("query_limit")),
        "max_file_size": _format_size(resolved_view.max_file_size),
        "max_total_size": _format_size(resolved_view.max_total_size),
    }

    summarization = {
        "enabled": bool(acms.get("summarize", True)),
        "max_tokens": acms.get("summary_max_tokens"),
    }

    phase_order = ["default", "strategize", "execute", "apply"]
    other_views = {
        phase: _view_status(policy, phase) for phase in phase_order if phase != view
    }

    return {
        "context_policy": context_policy,
        "limits": limits,
        "summarization": summarization,
        "other_views": other_views,
    }


def render_context_set_plain(payload: dict[str, Any], message: str) -> str:
    """Render the spec-aligned plain text output for context-set."""

    context_policy = payload["context_policy"]
    limits = payload["limits"]
    summarization = payload["summarization"]
    other_views = payload["other_views"]

    sections: list[str] = []

    cp_lines = [
        "Context Policy",
        f"  Project: {context_policy['project']}",
        f"  View: {context_policy['view']}",
        "  Include: "
        f"{_format_inline_list(context_policy['include_resources'], '(all)')}",
        f"  Exclude: {_format_inline_list(context_policy['exclude_paths'], '(none)')}",
    ]
    sections.append("\n".join(cp_lines))

    limits_lines = [
        "Limits",
        f"  Hot Tokens: {limits['hot_max_tokens']} (soft cap)",
        f"  Warm Decisions: {limits['warm_max_decisions']}",
        f"  Cold Decisions: {limits['cold_max_decisions']}",
    ]
    query_limit = limits["query_limit"]
    limits_lines.append(
        f"  Query Limit: {query_limit if query_limit is not None else '(default)'}"
    )
    limits_lines.append(f"  Max File Size: {limits['max_file_size']}")
    limits_lines.append(f"  Max Total Size: {limits['max_total_size']}")
    sections.append("\n".join(limits_lines))

    sum_max = summarization["max_tokens"]
    sum_max_str = sum_max if sum_max is not None else "(default)"
    summarization_lines = [
        "Summarization",
        f"  Enabled: {'yes' if summarization['enabled'] else 'no'}",
        f"  Max Tokens: {sum_max_str}",
    ]
    sections.append("\n".join(summarization_lines))

    other_view_lines = ["Other Views"]
    for phase, status in other_views.items():
        other_view_lines.append(f"  {phase}: {status}")
    sections.append("\n".join(other_view_lines))

    return "\n\n".join(sections) + f"\n\n[OK] {message}"


def render_context_set_rich(payload: dict[str, Any]) -> list[Panel]:
    """Build Rich panels matching the specification."""

    context_policy = payload["context_policy"]
    limits = payload["limits"]
    summarization = payload["summarization"]
    other_views = payload["other_views"]

    cp_lines = [
        f"[cyan bold]Project:[/cyan bold] {context_policy['project']}",
        f"[blue bold]View:[/blue bold] {context_policy['view']}",
        "[green bold]Include:[/green bold] "
        f"{_format_inline_list(context_policy['include_resources'], '(all)')}",
        "[yellow bold]Exclude:[/yellow bold] "
        f"{_format_inline_list(context_policy['exclude_paths'], '(none)')}",
    ]

    hot_tokens = limits["hot_max_tokens"]
    qlimit = limits["query_limit"]
    qlimit_str = qlimit if qlimit is not None else "(default)"
    limits_lines = [
        f"[magenta bold]Hot Tokens:[/magenta bold] {hot_tokens} (soft cap)",
        f"[magenta bold]Warm Decisions:[/magenta bold] {limits['warm_max_decisions']}",
        f"[magenta bold]Cold Decisions:[/magenta bold] {limits['cold_max_decisions']}",
        f"[blue bold]Query Limit:[/blue bold] {qlimit_str}",
        f"[blue bold]Max File Size:[/blue bold] {limits['max_file_size']}",
        f"[blue bold]Max Total Size:[/blue bold] {limits['max_total_size']}",
    ]

    sum_enabled = "yes" if summarization["enabled"] else "no"
    sum_max = summarization["max_tokens"]
    sum_max_str = sum_max if sum_max is not None else "(default)"
    summarization_lines = [
        f"[green bold]Enabled:[/green bold] {sum_enabled}",
        f"[blue bold]Max Tokens:[/blue bold] {sum_max_str}",
    ]

    other_view_lines = [
        f"[blue bold]{phase}:[/blue bold] {status}"
        for phase, status in other_views.items()
    ]

    return [
        Panel("\n".join(cp_lines), title="Context Policy", expand=False),
        Panel("\n".join(limits_lines), title="Limits", expand=False),
        Panel("\n".join(summarization_lines), title="Summarization", expand=False),
        Panel("\n".join(other_view_lines), title="Other Views", expand=False),
    ]
