"""Sitemap generation with in-memory TTL cache and hreflang alternates."""

import time

from quart import Response

from .core import fetch_all

# Process-local cache — valid for the current single-Hypercorn-worker deployment
# (Dockerfile: `--workers 1`). If worker count increases, replace with a
# DB-backed cache (e.g. a single-row SQLite table with an expires_at column).
_cache_xml: str = ""
_cache_timestamp: float = 0.0
CACHE_TTL_SECONDS: int = 3600  # 1 hour

LANGS = ("en", "de")
DEFAULT_LANG = "en"

# Pages with lang prefix but no meaningful lastmod
STATIC_PATHS = [
    "",           # landing
    "/features",
    "/about",
    "/terms",
    "/privacy",
    "/imprint",
    "/suppliers",
    "/markets",
    "/market-score",
    "/planner/",
    "/directory/",
]


def _url_entry(loc: str, alternates: list[tuple[str, str]], lastmod: str | None = None) -> str:
    """Build a single <url> entry with optional hreflang alternates and lastmod."""
    parts = [f"  <url>\n    <loc>{loc}</loc>"]
    for hreflang, href in alternates:
        parts.append(
            f'    <xhtml:link rel="alternate" hreflang="{hreflang}" href="{href}"/>'
        )
    if lastmod:
        parts.append(f"    <lastmod>{lastmod}</lastmod>")
    parts.append("  </url>")
    return "\n".join(parts)


def _lang_alternates(base: str, path: str) -> list[tuple[str, str]]:
    """Build hreflang alternate list for a lang-prefixed path."""
    alternates = []
    for lang in LANGS:
        alternates.append((lang, f"{base}/{lang}{path}"))
    alternates.append(("x-default", f"{base}/{DEFAULT_LANG}{path}"))
    return alternates


async def _generate_sitemap_xml(base_url: str) -> str:
    """Build sitemap XML from static paths + DB content."""
    base = base_url.rstrip("/")
    entries: list[str] = []

    # Static pages — both lang variants, no lastmod (rarely changes)
    for path in STATIC_PATHS:
        alternates = _lang_alternates(base, path)
        for lang in LANGS:
            entries.append(_url_entry(f"{base}/{lang}{path}", alternates))

    # Billing pricing — no lang prefix, no hreflang
    entries.append(_url_entry(f"{base}/billing/pricing", []))

    # Published articles — both lang variants with accurate lastmod.
    # Exclude noindex articles (thin data) to keep sitemap signal-dense.
    articles = await fetch_all(
        """SELECT url_path, COALESCE(updated_at, published_at) AS lastmod
           FROM articles
           WHERE status = 'published' AND noindex = 0 AND published_at <= datetime('now')
           ORDER BY published_at DESC
           LIMIT 25000"""
    )
    for article in articles:
        lastmod = article["lastmod"][:10] if article["lastmod"] else None
        alternates = _lang_alternates(base, article["url_path"])
        for lang in LANGS:
            entries.append(
                _url_entry(f"{base}/{lang}{article['url_path']}", alternates, lastmod)
            )

    # Supplier detail pages — both lang variants
    suppliers = await fetch_all(
        "SELECT slug, created_at FROM suppliers ORDER BY name LIMIT 5000"
    )
    for supplier in suppliers:
        lastmod = supplier["created_at"][:10] if supplier["created_at"] else None
        path = f"/directory/{supplier['slug']}"
        alternates = _lang_alternates(base, path)
        for lang in LANGS:
            entries.append(
                _url_entry(f"{base}/{lang}{path}", alternates, lastmod)
            )

    xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
    xml += (
        '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"\n'
        '        xmlns:xhtml="http://www.w3.org/1999/xhtml">\n'
    )
    xml += "\n".join(entries)
    xml += "\n</urlset>"
    return xml


def invalidate_sitemap_cache() -> None:
    """Force sitemap regeneration on next request."""
    global _cache_xml, _cache_timestamp  # noqa: PLW0603
    _cache_xml = ""
    _cache_timestamp = 0.0


async def sitemap_response(base_url: str) -> Response:
    """Return cached sitemap XML, regenerating if stale (1-hour TTL)."""
    global _cache_xml, _cache_timestamp  # noqa: PLW0603
    now = time.monotonic()
    if not _cache_xml or (now - _cache_timestamp) > CACHE_TTL_SECONDS:
        _cache_xml = await _generate_sitemap_xml(base_url)
        _cache_timestamp = now
    return Response(
        _cache_xml,
        content_type="application/xml",
        headers={"Cache-Control": f"public, max-age={CACHE_TTL_SECONDS}"},
    )
