"""Tests for the check-bearer-disable pre-commit guard.

The guard rejects `bearer:disable` directives that Bearer silently ignores:
same-line directives and directives with trailing prose after the rule id.
It must NOT flag well-formed directives or mere prose mentions.
"""

# allow: no-sut-import — the SUT is a pre-commit hook script under
# .pre-commit-hooks/, not a local_deep_research module; it is loaded via
# importlib below.

import importlib.util
from pathlib import Path

_HOOK = (
    Path(__file__).resolve().parents[2]
    / ".pre-commit-hooks"
    / "check-bearer-disable.py"
)


def _load():
    spec = importlib.util.spec_from_file_location("check_bearer_disable", _HOOK)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod


guard = _load()


# --- Python (#) -----------------------------------------------------------


def test_py_valid_bare_directive_passes():
    src = "# bearer:disable python_lang_sql_injection\nx = 1\n"
    assert guard._check_python(src) == []


def test_py_same_line_flagged():
    src = 'run(f"...{t}")  # noqa: S608  # bearer:disable python_lang_sql_injection\n'
    errors = guard._check_python(src)
    assert len(errors) == 1
    assert "same-line" in errors[0][1]


def test_py_trailing_prose_flagged():
    src = (
        "# bearer:disable python_lang_sql_injection -- because reasons\nx = 1\n"
    )
    errors = guard._check_python(src)
    assert len(errors) == 1
    assert "trailing text" in errors[0][1]


def test_py_emdash_trailing_prose_flagged():
    src = (
        "# bearer:disable python_lang_sql_injection — because reasons\nx = 1\n"
    )
    assert len(guard._check_python(src)) == 1


def test_py_docstring_mention_not_flagged():
    # A directive quoted inside a docstring must not be treated as real.
    src = (
        "def f():\n"
        '    """Carries a ``# bearer:disable python_lang_sql_injection`` note."""\n'
        "    return 1\n"
    )
    assert guard._check_python(src) == []


def test_py_comment_prose_mention_not_flagged():
    # An own-line comment that mentions the directive in backticked prose.
    src = "# suppressed with ``# bearer:disable python_lang_sql_injection`` above\nx = 1\n"
    assert guard._check_python(src) == []


def test_py_missing_rule_id_flagged():
    src = "# bearer:disable\nx = 1\n"
    errors = guard._check_python(src)
    assert len(errors) == 1
    assert "missing a rule id" in errors[0][1]


# --- JavaScript (//) ------------------------------------------------------


def test_js_valid_bare_directive_passes():
    src = "// bearer:disable javascript_lang_dangerous_insert_html\nel.innerHTML = x;\n"
    assert guard._check_js(src) == []


def test_js_same_line_flagged():
    src = "el.innerHTML = x; // bearer:disable javascript_lang_dangerous_insert_html\n"
    errors = guard._check_js(src)
    assert len(errors) == 1
    assert "same-line" in errors[0][1]


def test_js_trailing_prose_flagged():
    src = "    // bearer:disable javascript_lang_open_redirect -- hardcoded path\nfoo();\n"
    errors = guard._check_js(src)
    assert len(errors) == 1
    assert "trailing text" in errors[0][1]


def test_js_nested_prose_mention_not_flagged():
    src = "    // see the // bearer:disable rule note above\nfoo();\n"
    assert guard._check_js(src) == []


def test_js_url_with_double_slash_not_misflagged():
    src = '    const u = "https://example.com/x";\n'
    assert guard._check_js(src) == []


# --- Hardening cases (from adversarial review) ----------------------------


def test_py_prose_mention_on_code_line_not_flagged():
    # A code line whose comment merely mentions the text in prose (no embedded
    # `# bearer:disable`) must not be treated as a same-line directive.
    src = "cursor.execute(safe_q)  # parametrized; no bearer:disable needed\n"
    assert guard._check_python(src) == []


def test_py_bom_bare_directive_not_flagged(tmp_path):
    # A UTF-8 BOM must not make a valid own-line directive look same-line.
    # Exercises the real check_file() path (utf-8-sig read strips the BOM).
    p = tmp_path / "bom.py"
    p.write_bytes(
        b"\xef\xbb\xbf# bearer:disable python_lang_sql_injection\nx = 1\n"
    )
    assert guard.check_file(str(p)) == []


def test_py_lowercase_trailing_prose_flagged():
    src = "# bearer:disable python_lang_sql_injection because reasons\nx = 1\n"
    assert len(guard._check_python(src)) == 1


def test_py_comma_separated_rule_ids_pass():
    src = (
        "# bearer:disable python_lang_one_two, python_lang_three_four\nx = 1\n"
    )
    assert guard._check_python(src) == []


def test_js_directive_in_string_literal_not_flagged():
    # A `// bearer:disable ...` inside a string is not a comment.
    src = 'const H = "use // bearer:disable rule_x_y to suppress";\n'
    assert guard._check_js(src) == []


def test_js_same_line_with_url_in_string_flagged():
    # The `//` inside the URL string must not hide the genuine same-line dir.
    src = (
        'el.innerHTML = `<a href="https://x">${d}</a>`;'
        " // bearer:disable javascript_lang_dangerous_insert_html\n"
    )
    errors = guard._check_js(src)
    assert len(errors) == 1
    assert "same-line" in errors[0][1]


def test_js_lowercase_trailing_prose_flagged():
    src = "// bearer:disable javascript_lang_dangerous_insert_html trusted input\nf();\n"
    assert len(guard._check_js(src)) == 1


def test_js_block_comment_directive_flagged():
    src = "/* bearer:disable javascript_lang_dangerous_insert_html */\nf();\n"
    errors = guard._check_js(src)
    assert len(errors) == 1
    assert "block comment" in errors[0][1]


def test_js_jsdoc_block_directive_flagged():
    src = "/**\n * bearer:disable javascript_lang_dangerous_insert_html\n */\nf();\n"
    errors = guard._check_js(src)
    assert len(errors) == 1
    assert "block comment" in errors[0][1]


def test_js_block_comment_prose_mention_not_flagged():
    src = (
        "/**\n * suppressed by inline directives at call sites; module-level\n"
        " * would be ignored anyway.\n */\nf();\n"
    )
    assert guard._check_js(src) == []
