"""
Base template context shared by all apps.

This module no longer imports cart or menu_items services directly.
Each app provides its own context_fn that calls this base and adds
app-specific variables (cart data, menu_items, etc.).
"""
from __future__ import annotations

from datetime import datetime

from quart import request, g, current_app

from shared.config import config
from shared.utils import host_url
from shared.browser.app.utils import current_route_relative_path
from shared.infrastructure.urls import blog_url, market_url, cart_url, events_url


def _qs_filter_fn():
    """Build a qs_filter(dict) wrapper for sx components, or None.

    Sx components call ``qs_fn({"page": 2})``, ``qs_fn({"sort": "az"})``,
    ``qs_fn({"labels": ["organic", "local"]})``, etc.

    Simple keys (page, sort, search, liked, clear_filters) are forwarded
    to ``makeqs(**kwargs)``.  List-valued keys (labels, stickers, brands)
    represent *replacement* sets, so we rebuild the querystring from the
    current base with those overridden.
    """
    factory = getattr(g, "makeqs_factory", None)
    if not factory:
        return None
    makeqs = factory()

    def _qs(d: dict) -> str:
        from shared.browser.app.filters.qs_base import build_qs

        # Collect list-valued overrides
        list_overrides = {}
        for plural, singular in (("labels", "label"), ("stickers", "sticker"), ("brands", "brand")):
            if plural in d:
                list_overrides[singular] = list(d[plural] or [])

        simple = {k: v for k, v in d.items()
                  if k in ("page", "sort", "search", "liked", "clear_filters")}

        if not list_overrides:
            return makeqs(**simple)

        # For list overrides: get the base qs, parse out the overridden keys,
        # then rebuild with the new values.
        base_qs = makeqs(**simple)
        from urllib.parse import parse_qsl, urlencode
        params = [(k, v) for k, v in parse_qsl(base_qs.lstrip("?"))
                  if k not in list_overrides]
        for singular, vals in list_overrides.items():
            for v in vals:
                params.append((singular, v))
        return ("?" + urlencode(params)) if params else ""

    return _qs


async def base_context() -> dict:
    """
    Common template variables available in every app.

    Does NOT include cart, calendar_cart_entries, total, calendar_total,
    or menu_items — those are added by each app's context_fn.
    """
    is_htmx = request.headers.get("SX-Request") == "true" or request.headers.get("HX-Request") == "true"
    search = request.headers.get("X-Search", "")
    zap_filter = is_htmx and search == ""

    def base_url():
        return host_url()

    hx_select = "#main-panel"
    hx_select_search = (
        hx_select
        + ", #search-mobile, #search-count-mobile, #search-desktop, #search-count-desktop, #menu-items-nav-wrapper"
    )

    return {
        "is_htmx": is_htmx,
        "request": request,
        "now": datetime.now(),
        "current_local_href": current_route_relative_path(),
        "config": config(),
        "asset_url": current_app.jinja_env.globals.get("asset_url", lambda p: ""),
        "sort_options": [
            ("az", "A\u2013Z", "order/a-z.svg"),
            ("za", "Z\u2013A", "order/z-a.svg"),
            ("price-asc", "\u00a3 low\u2192high", "order/l-h.svg"),
            ("price-desc", "\u00a3 high\u2192low", "order/h-l.svg"),
        ],
        "zap_filter": zap_filter,
        "qs_filter": _qs_filter_fn(),
        "print": print,
        "base_url": base_url,
        "app_label": current_app.name,
        "base_title": config()["title"],
        "hx_select": hx_select,
        "hx_select_search": hx_select_search,
        "blog_url": blog_url,
        "market_url": market_url,
        "cart_url": cart_url,
        "events_url": events_url,
        "rights": getattr(g, "rights", {}),
    }
