"""Rich output formatters for all CLI commands."""

from __future__ import annotations

import json
import sys
from typing import Any

from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

console = Console()
err_console = Console(stderr=True)


# ── JSON mode ───────────────────────────────────────────────────────


def print_json(data: Any) -> None:
    print(json.dumps(data, indent=2, default=str))


# ── Audit ───────────────────────────────────────────────────────────


GRADE_COLORS = {"A": "green", "B": "blue", "C": "yellow", "D": "red", "F": "bold red"}


def format_audit_result(data: dict) -> None:
    # SEO-only / AEO-only responses nest scores inside seo_audit / aeo_audit
    sub = data.get("seo_audit") or data.get("aeo_audit") or {}
    grade = data.get("grade") or _pct_to_grade(sub.get("percentage"))
    color = GRADE_COLORS.get(grade, "white")
    pct = data.get("percentage") or sub.get("percentage") or 0
    url = data.get("url", "")

    console.print()
    console.print(Panel(
        f"[bold {color}]{grade}[/]  {pct:.0f}%  —  {url}",
        title="Audit Result",
        border_style=color,
    ))

    # Category breakdown
    categories = data.get("category_scores") or sub.get("category_scores", {})
    if categories:
        table = Table(title="Category Scores", show_lines=False)
        table.add_column("Category", style="bold")
        table.add_column("Score", justify="right")
        for cat, score in sorted(categories.items()):
            table.add_row(cat.replace("_", " ").title(), str(score))
        console.print(table)

    # Top recommendations
    recs = data.get("recommendations") or sub.get("recommendations", [])
    if recs:
        console.print(f"\n[bold]Top Issues ({len(recs)}):[/]")
        for rec in recs[:5]:
            if isinstance(rec, str):
                console.print(f"  [yellow]\u2022[/] {rec}")
            elif isinstance(rec, dict):
                console.print(f"  [yellow]\u2022[/] {rec.get('message', rec)}")


def _pct_to_grade(pct: float | None) -> str:
    if pct is None:
        return "?"
    if pct >= 91:
        return "A"
    if pct >= 76:
        return "B"
    if pct >= 51:
        return "C"
    if pct >= 26:
        return "D"
    return "F"


def format_audit_list(audits: list[dict]) -> None:
    table = Table(title="Recent Audits")
    table.add_column("ID", style="dim", max_width=8)
    table.add_column("URL")
    table.add_column("Grade", justify="center")
    table.add_column("Score", justify="right")
    table.add_column("Date", style="dim")
    for a in audits:
        grade = a.get("grade", "?")
        color = GRADE_COLORS.get(grade, "white")
        pct = a.get("percentage") or 0
        table.add_row(
            str(a.get("id", ""))[:8],
            a.get("url", ""),
            f"[{color}]{grade}[/]",
            f"{pct:.0f}%",
            str(a.get("created_at", ""))[:10],
        )
    console.print(table)


# ── Tone ────────────────────────────────────────────────────────────


def format_tone_profile(data: dict) -> None:
    profile = data.get("profile", data)
    brand = profile.get("brand_name", "N/A")
    archetype = profile.get("voice_archetype", "N/A")
    pitch = profile.get("elevator_pitch", "N/A")
    extracted = profile.get("extracted_from", "?")

    console.print()
    console.print(Panel(
        f"[bold]Brand:[/] {brand}\n"
        f"[bold]Archetype:[/] {archetype}\n"
        f"[bold]Pitch:[/] {pitch}\n"
        f"[bold]Articles analyzed:[/] {extracted}",
        title="Brand Voice Profile",
        border_style="cyan",
    ))

    # Core traits
    traits = profile.get("core_traits", [])
    if traits:
        console.print("\n[bold]Core Traits:[/]")
        for t in traits:
            if isinstance(t, dict):
                console.print(f"  [cyan]\u2022[/] [bold]{t.get('name', '')}[/]")
            else:
                console.print(f"  [cyan]\u2022[/] {t}")

    # Do's and Don'ts
    dos = profile.get("dos", [])
    donts = profile.get("donts", [])
    if dos or donts:
        table = Table(title="Do's & Don'ts", show_lines=False)
        table.add_column("Do", style="green", max_width=45)
        table.add_column("Don't", style="red", max_width=45)
        for i in range(max(len(dos), len(donts))):
            table.add_row(
                dos[i] if i < len(dos) else "",
                donts[i] if i < len(donts) else "",
            )
        console.print(table)


def format_tone_list(profiles: list[str]) -> None:
    if not profiles:
        console.print("[dim]No tone profiles found.[/]")
        return
    table = Table(title="Tone Profiles")
    table.add_column("#", style="dim", justify="right")
    table.add_column("Customer ID")
    for i, p in enumerate(profiles, 1):
        table.add_row(str(i), p)
    console.print(table)


# ── Optimize / Jobs ─────────────────────────────────────────────────


STATUS_STYLES = {
    "completed": "bold green",
    "failed": "bold red",
    "pending": "yellow",
    "running": "cyan",
    "auditing": "cyan",
    "tone_extracting": "cyan",
    "rewriting": "cyan",
}


def format_job_status(data: dict) -> None:
    status = data.get("status", "unknown")
    style = STATUS_STYLES.get(status, "white")

    console.print()
    console.print(Panel(
        f"[bold]Job:[/] {data.get('job_id', data.get('url', ''))}\n"
        f"[bold]Status:[/] [{style}]{status}[/]\n"
        f"[bold]URL:[/] {data.get('url', 'N/A')}",
        title="Optimization Job",
        border_style="blue",
    ))

    if status == "completed" and data.get("rewrite_result"):
        rw = data["rewrite_result"]
        console.print(f"  Tone alignment: [bold]{rw.get('tone_alignment_score', 0):.0%}[/]")
        console.print(f"  Issues fixed: [green]{len(rw.get('issues_addressed', []))}[/]")
        console.print(f"  Issues skipped: [dim]{len(rw.get('issues_skipped', []))}[/]")


def format_job_list(jobs: list[dict]) -> None:
    table = Table(title="Optimization Jobs")
    table.add_column("Job ID", style="dim", max_width=8)
    table.add_column("URL")
    table.add_column("Status", justify="center")
    table.add_column("Date", style="dim")
    for j in jobs:
        status = j.get("status", "?")
        style = STATUS_STYLES.get(status, "white")
        table.add_row(
            str(j.get("job_id", ""))[:8],
            j.get("url", ""),
            f"[{style}]{status}[/]",
            str(j.get("started_at", ""))[:10],
        )
    console.print(table)


# ── Freshness ───────────────────────────────────────────────────────


def format_freshness_result(data: dict) -> None:
    summary = data.get("summary", {})
    console.print()
    console.print(Panel(
        f"[bold]Domain:[/] {data.get('domain', 'N/A')}\n"
        f"[bold]Total URLs:[/] {data.get('total_urls_found', 0)}\n"
        f"[bold]Blog URLs:[/] {data.get('blog_urls_found', 0)}",
        title="Freshness Audit",
        border_style="green",
    ))

    results = data.get("results", [])
    if results:
        table = Table(title="URL Schema Status")
        table.add_column("URL", max_width=60)
        table.add_column("Schema", justify="center")
        table.add_column("Published", style="dim")
        for r in results[:20]:
            has = "[green]\u2713[/]" if r.get("has_schema") else "[red]\u2717[/]"
            table.add_row(
                r.get("url", "")[:60],
                has,
                str(r.get("published_date", ""))[:10],
            )
        console.print(table)
        if len(results) > 20:
            console.print(f"  [dim]... and {len(results) - 20} more URLs[/]")


# ── Export ──────────────────────────────────────────────────────────


def format_export(data: dict, output_file: str | None = None) -> None:
    md = data.get("markdown", "")
    if output_file:
        with open(output_file, "w") as f:
            f.write(md)
        console.print(f"[green]\u2713[/] Saved to {output_file}")
    else:
        console.print(md)


# ── Errors ──────────────────────────────────────────────────────────


def format_error(status_code: int, message: str) -> None:
    err_console.print(Panel(
        f"[bold red]Error {status_code}[/]\n{message}",
        border_style="red",
    ))
