"""Scrape and browse ASCII art from asciiart.eu."""
from __future__ import annotations

import re
import time
from typing import Generator
from urllib.parse import urljoin

import httpx
from bs4 import BeautifulSoup
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich import box as rbox

console = Console()
BASE = "https://www.asciiart.eu"

# All known categories from the site
CATEGORIES: dict[str, str] = {
    "animals": "/animals",
    "cats": "/animals/cats",
    "dogs": "/animals/dogs",
    "birds": "/animals/birds",
    "bears": "/animals/bears",
    "horses": "/animals/horses",
    "insects": "/animals/insects",
    "fish": "/animals/fish",
    "snakes": "/animals/snakes",
    "art": "/art-and-design",
    "books": "/books",
    "buildings": "/buildings-and-places",
    "cartoons": "/cartoons",
    "clothing": "/clothing-and-accessories",
    "comics": "/comics",
    "computers": "/computers",
    "linux": "/computers/linux",
    "electronics": "/electronics",
    "food": "/food-and-drinks",
    "holiday": "/holiday-and-events",
    "logos": "/logos",
    "misc": "/miscellaneous",
    "movies": "/movies",
    "music": "/music",
    "mythology": "/mythology",
    "nature": "/nature",
    "one-line": "/one-line",
    "people": "/people",
    "plants": "/plants",
    "religion": "/religion",
    "space": "/space",
    "sports": "/sports-and-outdoors",
    "television": "/television",
    "toys": "/toys",
    "vehicles": "/vehicles",
    "games": "/video-games",
    "weapons": "/weapons",
    "dragons": "/mythology/dragons",
    "skulls": "/miscellaneous/skulls",
    "hearts": "/holiday-and-events/valentines",
    "robots": "/computers",
    "stars": "/space",
}


def _get(url: str) -> BeautifulSoup | None:
    """Fetch URL and return BeautifulSoup."""
    try:
        headers = {"User-Agent": "ascii-maker/1.0 (educational)"}
        r = httpx.get(url, timeout=10, follow_redirects=True, headers=headers)
        r.raise_for_status()
        return BeautifulSoup(r.text, "html.parser")
    except Exception as e:
        console.print(f"[red]Fetch error: {e}[/]")
        return None


def _extract_arts(soup: BeautifulSoup) -> list[dict]:
    """Extract all art pieces from a category page."""
    results = []

    # asciiart.eu uses <pre> tags inside art cards
    # Try multiple selectors for robustness
    pres = soup.find_all("pre")
    for pre in pres:
        art_text = pre.get_text()
        if not art_text.strip() or len(art_text.strip()) < 5:
            continue

        # Try to find title nearby
        title = ""
        parent = pre.parent
        if parent:
            title_el = parent.find(class_=re.compile("title|name|caption", re.I))
            if title_el:
                title = title_el.get_text(strip=True)
            if not title:
                # Look at siblings
                for sib in parent.find_all(["h2", "h3", "p", "span"]):
                    t = sib.get_text(strip=True)
                    if t and len(t) < 80:
                        title = t
                        break

        results.append({"art": art_text, "title": title or f"Art #{len(results)+1}"})

    return results


def fetch_category(category: str, limit: int = 20) -> list[dict]:
    """Fetch ASCII art from a category. category can be a key or partial URL path."""
    path = CATEGORIES.get(category.lower(), category)
    if not path.startswith("http"):
        url = BASE + (path if path.startswith("/") else "/" + path)
    else:
        url = path

    console.print(f"[dim]Fetching {url}...[/]")
    soup = _get(url)
    if not soup:
        return []

    arts = _extract_arts(soup)
    return arts[:limit]


def search_online(query: str) -> list[dict]:
    """Search asciiart.eu (best effort via category matching + Google-site search hint)."""
    # Try matching query against known categories
    query_lower = query.lower()
    matches = [(k, v) for k, v in CATEGORIES.items() if query_lower in k or query_lower in v]

    results: list[dict] = []
    if matches:
        key, _ = matches[0]
        console.print(f"[dim]Matched category: {key}[/]")
        results = fetch_category(key, limit=10)

    if not results:
        console.print(f"[yellow]No direct match for '{query}'. Try 'am browse' to see all categories.[/]")

    return results


def browse_interactive() -> None:
    """Interactive category browser."""
    # Show all categories in a table
    table = Table(title="[bold cyan]ASCII Art Categories[/]", box=rbox.ROUNDED, show_header=True)
    table.add_column("Key", style="cyan", width=16)
    table.add_column("URL Path", style="dim")

    for key, path in sorted(CATEGORIES.items()):
        table.add_row(key, path)

    console.print(table)
    console.print("\n[bold]Usage:[/]  [cyan]am browse <category>[/]  — e.g. [cyan]am browse cats[/]")


def display_arts(arts: list[dict], pager: bool = True) -> str | None:
    """Display art pieces. Returns the last shown art text."""
    if not arts:
        console.print("[yellow]No art found.[/]")
        return None

    last = None
    for i, piece in enumerate(arts, 1):
        console.print(Panel(
            piece["art"],
            title=f"[yellow]{piece['title']}[/] [dim]({i}/{len(arts)})[/]",
            border_style="cyan",
            padding=(0, 1),
        ))
        last = piece["art"]

        if pager and i < len(arts) and i % 5 == 0:
            cont = console.input("[dim]── Press Enter for more, q to quit ──[/] ").strip()
            if cont.lower() == "q":
                break

    return last
