"""
Shared query-string primitives used by blog, market, and order qs modules.
"""
from __future__ import annotations

from urllib.parse import urlencode

# Sentinel meaning "leave value as-is" (used as default arg in makeqs)
KEEP = object()


def _iterify(x):
    """Normalize *x* to a list: None → [], scalar → [scalar], iterable → as-is."""
    if x is None:
        return []
    if isinstance(x, (list, tuple, set)):
        return x
    return [x]


def _norm(s: str) -> str:
    """Strip + lowercase — used for case-insensitive filter dedup."""
    return s.strip().lower()


def make_filter_set(
    base: list[str],
    add,
    remove,
    clear_filters: bool,
    *,
    single_select: bool = False,
) -> list[str]:
    """
    Build a deduplicated, sorted filter list.

    Parameters
    ----------
    base : list[str]
        Current filter values.
    add : str | list | None
        Value(s) to add.
    remove : str | list | None
        Value(s) to remove.
    clear_filters : bool
        If True, start from empty instead of *base*.
    single_select : bool
        If True, *add* **replaces** the list (blog tags/authors).
        If False, *add* is **appended** (market brands/stickers/labels).
    """
    add_list = [s for s in _iterify(add) if s is not None]

    if single_select:
        # Blog-style: adding replaces the entire set
        if add_list:
            table = {_norm(s): s for s in add_list}
        else:
            table = {_norm(s): s for s in base if not clear_filters}
    else:
        # Market-style: adding appends to the existing set
        table = {_norm(s): s for s in base if not clear_filters}
        for s in add_list:
            k = _norm(s)
            if k not in table:
                table[k] = s

    for s in _iterify(remove):
        if s is None:
            continue
        table.pop(_norm(s), None)

    return [table[k] for k in sorted(table)]


def build_qs(params: list[tuple[str, str]], *, leading_q: bool = True) -> str:
    """URL-encode *params* and optionally prepend ``?``."""
    qs = urlencode(params, doseq=True)
    return ("?" + qs) if (qs and leading_q) else qs
