"""The brand tokens keep their WCAG AA pairs.

Brand pass two (11 Sep) chose coral for the accent and derived four tones, each for one
job: small text on cream and white (--accent-ink), a button surface under white text
(--accent-strong), a label on the navy heroes (--accent-light). A later "just a touch
warmer" edit to tokens.css would silently drop a pair under 4.5:1 and no page would
error; the eyebrow labels on every hero are the ones that go first. This reads the
tokens file and checks the pairs the stylesheets actually use. Also pins that the
favicon set the shell links exists, since a missing icon is a 404 in every crawl log
and nothing else notices.
"""

import pathlib
import re

WEB = pathlib.Path(__file__).resolve().parents[1] / "web"


def _tokens() -> dict[str, str]:
    src = (WEB / "src" / "styles" / "tokens.css").read_text()
    return dict(re.findall(r"(--[a-z0-9-]+):\s*(#[0-9A-Fa-f]{6})\s*;", src))


def _lum(hex_colour: str) -> float:
    def channel(v: int) -> float:
        c = v / 255
        return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
    r, g, b = (int(hex_colour[i:i + 2], 16) for i in (1, 3, 5))
    return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b)


def contrast(a: str, b: str) -> float:
    la, lb = _lum(a), _lum(b)
    hi, lo = max(la, lb), min(la, lb)
    return (hi + 0.05) / (lo + 0.05)


# (foreground token, background token, minimum): the pairs app.css and the components draw.
PAIRS = [
    ("--accent-ink", "--surface-page", 4.5),     # eyebrows and airport codes on cream
    ("--accent-ink", "--surface-card", 4.5),     # the same on white cards
    ("--ink-inverse", "--accent-strong", 4.5),   # white text on the primary button
    ("--accent-light", "--navy-deep", 4.5),      # hero and header labels
    ("--accent-light", "--navy", 3.0),           # the mid-navy hero: large-text bar
    ("--ink", "--surface-page", 7.0),
    ("--ink-soft", "--surface-page", 4.5),
    ("--ink-inverse-soft", "--navy", 4.5),
]


class TestAccentContrast:
    def test_every_drawn_pair_meets_its_bar(self):
        t = _tokens()
        failures = [
            f"{fg} on {bg}: {contrast(t[fg], t[bg]):.2f} < {minimum}"
            for fg, bg, minimum in PAIRS
            if contrast(t[fg], t[bg]) < minimum
        ]
        assert not failures, "\n".join(failures)

    def test_gold_is_only_a_metal_now(self):
        """Decorative gold retired 11 Sep: the medal badge is the one place it may remain."""
        offenders = []
        for f in list((WEB / "src").rglob("*.css")) + list((WEB / "src").rglob("*.tsx")):
            if f.name == "tokens.css":
                continue
            body = f.read_text()
            if f.name == "Badge.css":
                body = body.split(".badge--medal {", 1)[0]
            if "var(--gold" in body:
                offenders.append(str(f.relative_to(WEB)))
        assert not offenders, f"gold used outside the medal badge: {offenders}"


class TestIconSet:
    def test_the_shell_links_icons_that_exist(self):
        shell = (WEB / "index.html").read_text()
        linked = re.findall(r'href="/([^"]+\.(?:ico|png|webmanifest))"', shell)
        assert "favicon.ico" in linked and "site.webmanifest" in linked
        for name in linked:
            assert (WEB / "public" / name).is_file(), f"{name} linked but missing from web/public"
