"""The CI-side token check (#2277).

The checker is stdlib-only and lives in scripts/ so CI can run it without an
install, so these tests import it by path rather than as a package.

Two properties matter more than the parsing: it must not fire on a COMMENT that
discusses a rule, and it must not fire on a longer literal that merely contains a
shorter one. Both would make the report untrustworthy, and an untrustworthy
report is worse than none — people stop reading it and the check stops working
while still passing.
"""
import importlib.util
import pathlib

import pytest

_PATH = pathlib.Path(__file__).resolve().parents[1] / "scripts" / "check_design_tokens.py"
_spec = importlib.util.spec_from_file_location("check_design_tokens", _PATH)
check = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(check)


SHEET = """
:root {
  /* surface */
  --fs-surface-page: #14171A;  /* page bg */
  --fs-text-primary: #E8E4D8;
}

/* SUPERSEDES — write the token, not the literal.
 * #fff -> --fs-text-primary
 * #ffffff -> --fs-text-primary
 * bold -> --fs-weight-medium
 */
"""


# --- reading the sheet ------------------------------------------------------

def test_declarations_after_a_comment_are_not_lost():
    """Anchored on the colon alone. Anchoring on `{` or `;` silently drops every
    declaration that follows a comment — a mistake made once already in this
    codebase, which lost three tokens without erroring."""
    assert check.declared_tokens(SHEET) == {"--fs-surface-page", "--fs-text-primary"}


def test_the_supersedes_block_is_read_from_the_sheet_not_hardcoded():
    """Rule #115: the checker must know nothing about any install's palette.
    Everything it enforces comes out of the stylesheet it is pointed at."""
    assert check.superseded_literals(SHEET) == {
        "#fff": "--fs-text-primary",
        "#ffffff": "--fs-text-primary",
        "bold": "--fs-weight-medium",
    }


def test_a_sheet_with_no_supersedes_block_yields_nothing():
    assert check.superseded_literals(":root { --a: 1px; }") == {}


# --- the literal matcher ----------------------------------------------------

def test_a_short_hex_does_not_match_inside_a_longer_one():
    """`#fff` firing on `#ffffff` would send someone to change correct code."""
    assert check._literal_pattern("#fff").search("color: #ffffff;") is None
    assert check._literal_pattern("#fff").search("color: #fff;") is not None


def test_the_match_is_case_insensitive():
    assert check._literal_pattern("#ffffff").search("color: #FFFFFF;") is not None


def test_a_keyword_does_not_match_inside_a_longer_word():
    """`bold` must not fire on `font-weight: bolder` or a class named
    `.bold-label` — the boundary is what keeps the report readable."""
    assert check._literal_pattern("bold").search("font-weight: bolder;") is None
    assert check._literal_pattern("bold").search(".bold-label { }") is None
    assert check._literal_pattern("bold").search("font-weight: bold;") is not None


# --- reading a component ----------------------------------------------------

def test_only_the_style_block_of_an_sfc_is_read(tmp_path):
    """A hex in a template attribute or a script string is not a stylesheet
    violation, and reporting it would bury the ones that are."""
    sfc = tmp_path / "X.vue"
    sfc.write_text(
        '<template><div data-x="#fff">white</div></template>\n'
        '<script setup>const c = "#fff";</script>\n'
        '<style scoped>.a { color: var(--fs-text-primary); }</style>\n'
    )
    css = check.style_source(sfc)
    assert "--fs-text-primary" in css
    assert "#fff" not in css


def test_a_comment_explaining_a_rule_is_not_a_violation(tmp_path):
    """LOAD-BEARING, and it fired on the first real run. A comment documenting
    why a literal is avoided necessarily contains that literal — this codebase's
    own stylesheet says so about `#fff`. A checker that flags the documentation
    of a rule teaches people to stop documenting rules."""
    sfc = tmp_path / "Y.vue"
    sfc.write_text(
        "<style scoped>\n"
        "/* Deliberately NOT #fff — pure white is never text. */\n"
        ".a { color: var(--fs-text-primary); }\n"
        "</style>\n"
    )
    css = check.style_source(sfc)
    assert check._literal_pattern("#fff").search(css) is None


def test_a_plain_css_file_is_read_whole(tmp_path):
    css_file = tmp_path / "shared.css"
    css_file.write_text(".a { color: #fff; }")
    assert "#fff" in check.style_source(css_file)


# --- the gate ---------------------------------------------------------------

def _run(tmp_path, sheet: str, component: str, monkeypatch, capsys):
    (tmp_path / "assets").mkdir(parents=True, exist_ok=True)
    sheet_path = tmp_path / "assets" / "theme.css"
    sheet_path.write_text(sheet)
    (tmp_path / "C.vue").write_text(f"<style>{component}</style>")
    monkeypatch.setattr(
        "sys.argv",
        ["check", "--sheet", str(sheet_path), "--root", str(tmp_path)],
    )
    code = check.main()
    return code, capsys.readouterr().out


def test_an_unresolvable_reference_fails_the_build(tmp_path, monkeypatch, capsys):
    """The one hard gate. It is safe to gate on because the count is zero today —
    a ratchet holding a line already reached, not a backlog that keeps CI red."""
    code, out = _run(tmp_path, SHEET, ".a { color: var(--nope); }", monkeypatch, capsys)
    assert code == 1
    assert "--nope" in out


def test_a_resolvable_reference_passes(tmp_path, monkeypatch, capsys):
    code, out = _run(
        tmp_path, SHEET, ".a { color: var(--fs-text-primary); }", monkeypatch, capsys
    )
    assert code == 0
    assert "every var() reference resolves" in out


def test_a_locally_declared_property_is_not_unresolved(tmp_path, monkeypatch, capsys):
    """A component may legitimately define its own custom property for local use —
    a keyframe variable, a per-instance override. Only a reference to a name that
    exists NOWHERE is broken."""
    code, _ = _run(
        tmp_path, SHEET, ".a { --local: 4px; padding: var(--local); }", monkeypatch, capsys
    )
    assert code == 0


def test_a_superseded_literal_reports_but_does_not_fail(tmp_path, monkeypatch, capsys):
    """Hundreds exist. Gating would make a permanently-red job, which is a check
    nobody reads — worse than no check at all."""
    code, out = _run(tmp_path, SHEET, ".a { color: #fff; }", monkeypatch, capsys)
    assert code == 0
    assert "#fff -> --fs-text-primary" in out


def test_a_missing_stylesheet_is_an_error_not_a_pass(tmp_path, monkeypatch, capsys):
    """If the sheet moves, the check must fail loudly rather than silently
    passing with zero tokens to compare against — which would look identical to
    a clean run."""
    monkeypatch.setattr(
        "sys.argv", ["check", "--sheet", str(tmp_path / "gone.css"), "--root", str(tmp_path)]
    )
    assert check.main() == 2
