"""sRGB colour blending for the token layer.

The Magogi brand's semantic tokens are defined upstream with CSS
``color-mix(in srgb, A p%, B)`` expressions (see
``docs/plans/desktop-ui-redesign/00-brand-understanding.md`` §2b). Qt
has no ``color-mix``, so :func:`mix` reproduces the same linear
per-channel blend at import time — keeping parity with the generated
web tokens by construction instead of hand-transcribed hex values.

This module is deliberately Qt-free so the token layer stays
importable (and unit-testable) without PySide6.
"""

from __future__ import annotations

WHITE = "#ffffff"
BLACK = "#000000"

_HEX_LEN = 7  # "#rrggbb"


def _channels(color: str) -> tuple[int, int, int]:
    """Parse ``#rrggbb`` into an ``(r, g, b)`` tuple or raise ``ValueError``."""
    if len(color) != _HEX_LEN or not color.startswith("#"):
        raise ValueError(f"expected '#rrggbb' hex colour, got {color!r}")
    try:
        return (int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16))
    except ValueError as exc:
        raise ValueError(f"expected '#rrggbb' hex colour, got {color!r}") from exc


def mix(a: str, pct: int, b: str) -> str:
    """Blend ``pct`` percent of colour ``a`` with ``100 - pct`` percent of ``b``.

    Mirrors CSS ``color-mix(in srgb, a pct%, b)``: a linear per-channel
    sRGB interpolation, rounded to the nearest integer channel value.
    Returns lowercase ``#rrggbb``.
    """
    if not 0 <= pct <= 100:
        raise ValueError(f"pct must be 0..100, got {pct}")
    ar, ag, ab_ = _channels(a)
    br, bg, bb = _channels(b)
    frac = pct / 100.0
    r = round(ar * frac + br * (1.0 - frac))
    g = round(ag * frac + bg * (1.0 - frac))
    b_ = round(ab_ * frac + bb * (1.0 - frac))
    return f"#{r:02x}{g:02x}{b_:02x}"


__all__ = ["BLACK", "WHITE", "mix"]
