"""
test_gateignore.py — .gateignore softens the 'no applicable detector' notice WITHOUT becoming a bypass.

Guards two things:
  - load_gateignore parses globs, stripping `#` comments + blank lines.
  - the loud-vs-calm decision: a DECLARED out-of-scope file goes calm ('out of security scope'); an UNDECLARED
    uncovered file stays LOUD ('NOT a security clean'). The filter is exactly the one prevent.main uses.
.gateignore NEVER removes a file from gating (files all still run through the gate) — that invariant is structural
in prevent.main (no partition), so there is nothing to suppress here; this only guards the wording branch.
"""
import importlib.util, os

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


def _load(name, path):
    spec = importlib.util.spec_from_file_location(name, path)
    mod = importlib.util.module_from_spec(spec); spec.loader.exec_module(mod); return mod


prevent = _load("sg_prevent", os.path.join(ROOT, "prevent", "prevent.py"))
registry = _load("sg_reg_gi", os.path.join(ROOT, "prevent", "registry.py"))


def _in_scope(files, patterns):
    """The exact loud/calm partition prevent.main applies: a file is in-scope (still loud) unless declared."""
    return [f for f in files if not any(registry.glob_match(f, p) for p in patterns)]


def test_load_strips_comments_and_blanks(tmp_path):
    (tmp_path / ".gateignore").write_text(
        "# header comment\n\n*.py        # trailing comment\n\n.visual/**\n   \n")
    assert prevent.load_gateignore(str(tmp_path)) == ["*.py", ".visual/**"]


def test_missing_file_is_empty(tmp_path):
    assert prevent.load_gateignore(str(tmp_path)) == []


def test_all_declared_files_go_calm(tmp_path):
    (tmp_path / ".gateignore").write_text("*.py\n*.md\n.visual/**\n")
    pats = prevent.load_gateignore(str(tmp_path))
    files = ["prevent/verdict.py", "README.md", ".visual/index.html"]
    assert _in_scope(files, pats) == []          # all declared -> calm 'out of security scope'


def test_undeclared_uncovered_file_stays_loud(tmp_path):
    (tmp_path / ".gateignore").write_text("*.py\n")
    pats = prevent.load_gateignore(str(tmp_path))
    files = ["bench.py", "domains/security/corpus/x/vuln.ts"]
    assert _in_scope(files, pats) == ["domains/security/corpus/x/vuln.ts"]  # the .ts is a real blind spot -> loud


def test_empty_gateignore_keeps_everything_loud(tmp_path):
    files = ["a.py", "b.ts"]
    assert _in_scope(files, prevent.load_gateignore(str(tmp_path))) == files
