"""Security tests for instance_id validation.

Tests path traversal prevention at CLI boundary and defense-in-depth
validation in state management layer.

Spec source: auto-rm.auto-rm-gate-fix - security blocker fix
"""

import pytest

from anima.core.ids import validate_instance_id


class TestValidateInstanceId:
    """Tests for validate_instance_id function."""

    def test_valid_instance_id_passes(self) -> None:
        """Valid instance_id passes validation."""
        assert validate_instance_id("inst_abc123") == "inst_abc123"

    def test_valid_instance_id_with_underscores(self) -> None:
        """Valid instance_id with underscores passes."""
        assert validate_instance_id("inst_test_123") == "inst_test_123"

    def test_valid_instance_id_with_hyphens(self) -> None:
        """Valid instance_id with hyphens passes."""
        assert validate_instance_id("inst-test-123") == "inst-test-123"

    def test_valid_instance_id_generated(self) -> None:
        """Generated instance_id passes validation."""
        from anima.core.ids import generate_instance_id

        inst_id = generate_instance_id()
        # Should not raise
        validate_instance_id(inst_id)

    def test_empty_fails(self) -> None:
        """Empty string fails validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("")

    def test_path_traversal_parent_fails(self) -> None:
        """Path traversal with '..' fails validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("../../../etc/passwd")

    def test_path_traversal_parent_in_middle_fails(self) -> None:
        """Path traversal with '..' in middle fails."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("inst_abc../../etc/passwd")

    def test_path_separator_slash_fails(self) -> None:
        """Path separator '/' fails validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("inst/abc")

    def test_path_separator_backslash_fails(self) -> None:
        """Path separator '\\' fails validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("inst\\abc")

    def test_hidden_file_fails(self) -> None:
        """Hidden file (starting with '.') fails validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id(".hidden")

    def test_non_printable_fails(self) -> None:
        """Non-printable characters fail validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("inst_abc\x00def")

    def test_too_long_fails(self) -> None:
        """Excessively long instance_id fails validation."""
        import deal

        long_id = "a" * 300
        with pytest.raises(deal.PreContractError):
            validate_instance_id(long_id)

    def test_control_characters_fails(self) -> None:
        """Control characters fail validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("inst_abc\n")

    def test_null_byte_fails(self) -> None:
        """Null byte fails validation."""
        import deal

        with pytest.raises(deal.PreContractError):
            validate_instance_id("inst_\x00abc")


class TestDeleteAgentStateSecurity:
    """Tests for delete_agent_state defense-in-depth validation."""

    def test_delete_valid_instance_id(self, tmp_state_dir) -> None:
        """Valid instance_id deletion succeeds."""
        from anima.core.schemas import JobSpec, LifecycleType
        from anima.shell.state import create_agent_state, delete_agent_state

        # Create agent
        job = JobSpec(
            instance_id="inst_test_valid",
            persona_ref="test",
            lifecycle=LifecycleType.ephemeral,
        )
        result = create_agent_state(
            instance_id="inst_test_valid",
            persona_name="test-persona",
            job=job,
        )
        assert result

        # Delete should succeed
        delete_result = delete_agent_state("inst_test_valid")
        from returns.result import Success

        assert isinstance(delete_result, Success)

    def test_delete_path_traversal_blocked(self, tmp_state_dir) -> None:
        """Path traversal attempt is blocked by delete_agent_state."""
        from returns.result import Failure

        from anima.shell.state import delete_agent_state

        # Attempt to delete parent directory via path traversal
        result = delete_agent_state("../../../tmp")
        assert isinstance(result, Failure)
        assert "Invalid instance_id" in str(result.failure())

    def test_delete_path_separator_blocked(self, tmp_state_dir) -> None:
        """Path separator in instance_id is blocked."""
        from returns.result import Failure

        from anima.shell.state import delete_agent_state

        result = delete_agent_state("inst/../../tmp")
        assert isinstance(result, Failure)
        # Error message indicates validation failure
        error_msg = str(result.failure()).lower()
        assert "invalid" in error_msg

    def test_delete_agents_dir_itself_blocked(self, tmp_state_dir) -> None:
        """Deleting agents directory itself is blocked."""
        from returns.result import Failure

        from anima.shell.state import delete_agent_state

        # Try to delete agents directory by using '.' as instance_id
        # This should be blocked by the validation
        result = delete_agent_state(".")
        assert isinstance(result, Failure)
        # Should fail on either the '.' check or the path check
        error_msg = str(result.failure()).lower()
        assert "invalid" in error_msg or "cannot start with" in error_msg
