"""
llmpm trending  — show top trending models by likes on HuggingFace Hub
"""

from __future__ import annotations

import json
import urllib.error
import urllib.parse
import urllib.request
from typing import Any

import click
from rich.console import Console
from rich.markup import escape
from rich.rule import Rule
from rich.table import Table
from rich import box

from llmpm import display

_console = Console()

HF_API = "https://huggingface.co/api/models"
LLMPM_MODEL_URL = "https://llmpm.co/models/{repo_id}"

CATEGORIES: dict[str, dict[str, Any]] = {
    "text-generation": {
        "label": "Text Generation",
        "color": "magenta",
        "limit": 5,
    },
    "text-to-image": {
        "label": "Text to Image",
        "color": "dark_orange",
        "limit": 5,
    },
}


def _fmt_number(n: int | None) -> str:
    if n is None:
        return "—"
    if n >= 1_000_000:
        return f"{n / 1_000_000:.1f}M"
    if n >= 1_000:
        return f"{n / 1_000:.1f}K"
    return str(n)


def _fetch_trending(pipeline_tag: str, limit: int) -> list[dict]:
    params: dict[str, Any] = {
        "limit": limit,
        "skip": 0,
        "sort": "likes",
        "direction": -1,
        "pipeline_tag": pipeline_tag,
    }
    url = HF_API + "?" + urllib.parse.urlencode(params)
    try:
        req = urllib.request.Request(url, headers={"User-Agent": "llmpm-cli/1.0"})
        with urllib.request.urlopen(req, timeout=15) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as exc:
        raise click.ClickException(
            f"HuggingFace API returned HTTP {exc.code}: {exc.reason}"
        ) from exc
    except urllib.error.URLError as exc:
        raise click.ClickException(f"Network error: {exc.reason}") from exc
    except Exception as exc:  # pylint: disable=broad-except
        raise click.ClickException(f"Unexpected error: {exc}") from exc


def _render_section(pipeline_tag: str, models: list[dict], color: str, label: str) -> None:
    _console.print(Rule(f"[bold {color}]{label}[/]", style=f"dim {color}"))
    _console.print()

    table = Table(
        show_header=True,
        header_style="bold dim",
        border_style="dim",
        box=box.ROUNDED,
        padding=(0, 1),
        show_lines=False,
    )
    table.add_column("#", style="dim", width=3, justify="right")
    table.add_column("Model", min_width=34)
    table.add_column("Downloads", justify="right", style="green", min_width=10)
    table.add_column("Likes", justify="right", style="yellow", min_width=7)
    table.add_column("Link", style="dim cyan", min_width=30)

    for idx, model in enumerate(models, 1):
        repo_id = model.get("modelId") or model.get("id") or "?"
        downloads = _fmt_number(model.get("downloads"))
        likes = _fmt_number(model.get("likes"))
        link = LLMPM_MODEL_URL.format(repo_id=repo_id)
        link_text = f"[link={link}]{link}[/link]"

        table.add_row(
            str(idx),
            f"[bold]{escape(repo_id)}[/]",
            downloads,
            likes,
            link_text,
        )

    _console.print(table)
    _console.print()


# ── trending ──────────────────────────────────────────────────────────────────

@click.command("trending")
def trending() -> None:
    """Show top trending models by likes for text-generation and text-to-image."""
    display.header("trending models")
    display.blank()

    with _console.status("[dim]Fetching trending models from HuggingFace…[/]"):
        results: dict[str, list[dict]] = {}
        for pipeline_tag, cfg in CATEGORIES.items():
            results[pipeline_tag] = _fetch_trending(pipeline_tag, cfg["limit"])

    for pipeline_tag, cfg in CATEGORIES.items():
        models = results[pipeline_tag]
        if not models:
            display.warn(f"No results for {cfg['label']}.")
            continue
        _render_section(pipeline_tag, models, cfg["color"], cfg["label"])

    _console.print(
        f"  [dim]Install any model:[/]  "
        f"[bold cyan]llmpm install <model-id>[/]\n"
    )
