"""Security tests — validate fixes for audit findings."""
import os
import tempfile

import pytest


# -----------------------------------------------------------------------
# Fix 2: SQL injection in ioc_db._count()
# -----------------------------------------------------------------------

class TestIOCTableWhitelist:
    @pytest.fixture(autouse=True)
    def setup_db(self, tmp_path):
        from ayn_antivirus.signatures.db.ioc_db import IOCDatabase

        self.db = IOCDatabase(tmp_path / "test_ioc.db")
        self.db.initialize()
        yield
        self.db.close()

    def test_valid_tables(self):
        for table in ("ioc_ips", "ioc_domains", "ioc_urls"):
            assert self.db._count(table) >= 0

    def test_injection_blocked(self):
        with pytest.raises(ValueError, match="Invalid table"):
            self.db._count("ioc_ips; DROP TABLE ioc_ips; --")

    def test_arbitrary_table_blocked(self):
        with pytest.raises(ValueError, match="Invalid table"):
            self.db._count("evil_table")

    def test_valid_tables_frozenset(self):
        from ayn_antivirus.signatures.db.ioc_db import IOCDatabase

        assert isinstance(IOCDatabase._VALID_TABLES, frozenset)
        assert IOCDatabase._VALID_TABLES == {"ioc_ips", "ioc_domains", "ioc_urls"}


# -----------------------------------------------------------------------
# Fix 4: Quarantine ID path traversal
# -----------------------------------------------------------------------

class TestQuarantineIDValidation:
    @pytest.fixture(autouse=True)
    def setup_vault(self, tmp_path):
        from ayn_antivirus.quarantine.vault import QuarantineVault

        self.vault = QuarantineVault(
            tmp_path / "vault", tmp_path / "vault" / ".key"
        )

    def test_traversal_blocked(self):
        with pytest.raises(ValueError, match="Invalid quarantine ID"):
            self.vault._validate_qid("../../etc/passwd")

    def test_too_short(self):
        with pytest.raises(ValueError, match="Invalid quarantine ID"):
            self.vault._validate_qid("abc")

    def test_too_long(self):
        with pytest.raises(ValueError, match="Invalid quarantine ID"):
            self.vault._validate_qid("a" * 33)

    def test_non_hex(self):
        with pytest.raises(ValueError, match="Invalid quarantine ID"):
            self.vault._validate_qid("GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG")

    def test_uppercase_hex_rejected(self):
        with pytest.raises(ValueError, match="Invalid quarantine ID"):
            self.vault._validate_qid("A" * 32)

    def test_valid_id(self):
        assert self.vault._validate_qid("a" * 32) == "a" * 32
        assert self.vault._validate_qid("0123456789abcdef" * 2) == "0123456789abcdef" * 2

    def test_whitespace_stripped(self):
        padded = "  " + "a" * 32 + "  "
        assert self.vault._validate_qid(padded) == "a" * 32


# -----------------------------------------------------------------------
# Fix 3: Quarantine restore path traversal
# -----------------------------------------------------------------------

class TestRestorePathValidation:
    @pytest.fixture(autouse=True)
    def setup_vault(self, tmp_path):
        from ayn_antivirus.quarantine.vault import QuarantineVault

        self.vault = QuarantineVault(
            tmp_path / "vault", tmp_path / "vault" / ".key"
        )

    def test_etc_blocked(self):
        with pytest.raises(ValueError, match="protected path"):
            self.vault._validate_restore_path("/etc/shadow")

    def test_usr_bin_blocked(self):
        with pytest.raises(ValueError, match="protected path"):
            self.vault._validate_restore_path("/usr/bin/evil")

    def test_cron_blocked(self):
        with pytest.raises(ValueError, match="Refusing to restore"):
            self.vault._validate_restore_path("/etc/cron.d/backdoor")

    def test_systemd_blocked(self):
        with pytest.raises(ValueError, match="Refusing to restore"):
            self.vault._validate_restore_path("/etc/systemd/system/evil.service")

    def test_safe_path_allowed(self):
        result = self.vault._validate_restore_path("/tmp/restored.txt")
        assert result.name == "restored.txt"


# -----------------------------------------------------------------------
# Fix 5: Container scanner command injection
# -----------------------------------------------------------------------

class TestContainerIDSanitization:
    @pytest.fixture(autouse=True)
    def setup_scanner(self):
        from ayn_antivirus.scanners.container_scanner import ContainerScanner

        self.scanner = ContainerScanner()

    def test_semicolon_injection(self):
        with pytest.raises(ValueError):
            self.scanner._sanitize_id("abc; rm -rf /")

    def test_dollar_injection(self):
        with pytest.raises(ValueError):
            self.scanner._sanitize_id("$(cat /etc/shadow)")

    def test_backtick_injection(self):
        with pytest.raises(ValueError):
            self.scanner._sanitize_id("`whoami`")

    def test_pipe_injection(self):
        with pytest.raises(ValueError):
            self.scanner._sanitize_id("abc|cat /etc/passwd")

    def test_ampersand_injection(self):
        with pytest.raises(ValueError):
            self.scanner._sanitize_id("abc && echo pwned")

    def test_empty_rejected(self):
        with pytest.raises(ValueError):
            self.scanner._sanitize_id("")

    def test_too_long_rejected(self):
        with pytest.raises(ValueError):
            self.scanner._sanitize_id("a" * 200)

    def test_valid_ids(self):
        assert self.scanner._sanitize_id("abc123") == "abc123"
        assert self.scanner._sanitize_id("my-container") == "my-container"
        assert self.scanner._sanitize_id("web_app.v2") == "web_app.v2"
        assert self.scanner._sanitize_id("a1b2c3d4e5f6") == "a1b2c3d4e5f6"


# -----------------------------------------------------------------------
# Fix 6: Config key validation
# -----------------------------------------------------------------------

def test_config_key_whitelist_in_cli():
    """The config --set handler should reject unknown keys.

    We verify by inspecting the CLI module source for the VALID_CONFIG_KEYS
    set and its guard clause, since it's defined inside a Click command body.
    """
    import inspect
    import ayn_antivirus.cli as cli_mod

    src = inspect.getsource(cli_mod)
    assert "VALID_CONFIG_KEYS" in src
    assert '"scan_paths"' in src
    assert '"dashboard_port"' in src
    # Verify the guard clause exists
    assert "if key not in VALID_CONFIG_KEYS" in src


# -----------------------------------------------------------------------
# Fix 9: API query param validation
# -----------------------------------------------------------------------

def test_safe_int_helper():
    from ayn_antivirus.dashboard.api import _safe_int

    assert _safe_int("50", 10) == 50
    assert _safe_int("abc", 10) == 10
    assert _safe_int("", 10) == 10
    assert _safe_int(None, 10) == 10
    assert _safe_int("-5", 10, min_val=1) == 1
    assert _safe_int("9999", 10, max_val=500) == 500
    assert _safe_int("0", 10, min_val=1) == 1
