"""
Tests for the check-url-security pre-commit hook.

Covers regressions for previously-missed patterns:
- substring-based skip list (bare "test"/"spec") silently skipped production
  files such as attestation_service.js, latest_products.js, respectful_handler.js
- `has_basic_protection` short-circuit was trivially satisfied by a comment
  mentioning "javascript:" plus any unrelated .includes()/.startsWith()
"""

import subprocess
import sys
import tempfile
from pathlib import Path


HOOK_SCRIPT = (
    Path(__file__).parent.parent.parent
    / ".pre-commit-hooks"
    / "check-url-security.py"
)


def _run_hook(content: str, filename: str) -> subprocess.CompletedProcess:
    """Write content to a temp file with a specific path and run the hook."""
    with tempfile.TemporaryDirectory() as d:
        path = Path(d) / filename
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(content)
        return subprocess.run(
            [sys.executable, str(HOOK_SCRIPT), str(path)],
            capture_output=True,
            text=True,
        )


UNPROTECTED_EXTERNAL = (
    'fetch("https://api.example.com/data");\nelement.href = userProvidedUrl;\n'
)


class TestSkipListDoesNotSilentlyExempt:
    """Files whose names merely contain 'test'/'spec' as substrings must be scanned."""

    def test_attestation_service_is_scanned(self):
        """'attestation_service.js' contains substring 'test' but is not a test file."""
        result = _run_hook(UNPROTECTED_EXTERNAL, "attestation_service.js")
        assert result.returncode == 1
        assert "URL Security Issues" in result.stdout

    def test_latest_products_is_scanned(self):
        """'latest_products.js' contains substring 'test'."""
        result = _run_hook(UNPROTECTED_EXTERNAL, "latest_products.js")
        assert result.returncode == 1

    def test_respectful_is_scanned(self):
        """'respectful_handler.js' contains substring 'spec'."""
        result = _run_hook(UNPROTECTED_EXTERNAL, "respectful_handler.js")
        assert result.returncode == 1


class TestSkipListStillExemptsRealTestFiles:
    """Legitimate test / vendor / build files must remain skipped."""

    def test_test_prefix_skipped(self):
        result = _run_hook(UNPROTECTED_EXTERNAL, "test_foo.js")
        assert result.returncode == 0

    def test_tests_directory_skipped(self):
        result = _run_hook(UNPROTECTED_EXTERNAL, "tests/helpers.js")
        assert result.returncode == 0

    def test_dot_spec_suffix_skipped(self):
        result = _run_hook(UNPROTECTED_EXTERNAL, "foo.spec.js")
        assert result.returncode == 0

    def test_dot_test_suffix_skipped(self):
        result = _run_hook(UNPROTECTED_EXTERNAL, "foo.test.js")
        assert result.returncode == 0

    def test_vendor_directory_skipped(self):
        result = _run_hook(UNPROTECTED_EXTERNAL, "vendor/lib.js")
        assert result.returncode == 0

    def test_node_modules_directory_skipped(self):
        result = _run_hook(UNPROTECTED_EXTERNAL, "node_modules/lodash/index.js")
        assert result.returncode == 0

    def test_min_suffix_skipped(self):
        result = _run_hook(UNPROTECTED_EXTERNAL, "app.min.js")
        assert result.returncode == 0


class TestBasicProtectionShortCircuitRemoved:
    """The weak has_basic_protection short-circuit should no longer mask gaps."""

    def test_comment_mentioning_javascript_and_unrelated_includes_does_not_bypass(
        self,
    ):
        """A comment mentioning 'javascript:' + any unrelated .includes() used to pass."""
        content = (
            "// Do not use javascript: schemes anywhere in this app.\n"
            'if (items.includes("foo")) { doThing(); }\n'
            'fetch("https://api.example.com/data");\n'
            "element.href = userUrl;\n"
        )
        result = _run_hook(content, "app.js")
        assert result.returncode == 1
        assert "URL validation" in result.stdout

    def test_file_with_real_urlvalidator_passes(self):
        """Files that actually import URLValidator still pass."""
        content = (
            'import { URLValidator } from "./url-validator.js";\n'
            'fetch("https://api.example.com/data");\n'
            'URLValidator.safeAssign(element, "href", userUrl);\n'
        )
        result = _run_hook(content, "app.js")
        assert result.returncode == 0

    def test_file_with_no_external_urls_passes(self):
        """Files that don't handle external URLs should pass."""
        content = 'element.textContent = "hello";\n'
        result = _run_hook(content, "app.js")
        assert result.returncode == 0
