"""Tests for Permission Manager.

Tests cover:
- PermissionGrant: creation, expiry, matching, hierarchy
- PermissionManager: grant, revoke, check, require, list, defaults
- Edge cases: wildcards, expiration, default deny/allow
"""

from datetime import datetime, timedelta

import pytest
import pytest_asyncio

from app.services.safety.exceptions import PermissionDeniedError
from app.services.safety.models import (
    ActionMetadata,
    ActionRequest,
    ActionType,
    PermissionLevel,
    ResourceType,
)
from app.services.safety.permissions.manager import PermissionGrant, PermissionManager

# ============================================================================
# Fixtures
# ============================================================================


@pytest.fixture
def action_metadata() -> ActionMetadata:
    """Create standard action metadata for tests."""
    return ActionMetadata(
        agent_id="test-agent",
        project_id="test-project",
        session_id="test-session",
    )


@pytest_asyncio.fixture
async def permission_manager() -> PermissionManager:
    """Create a PermissionManager for testing."""
    return PermissionManager(default_deny=True)


@pytest_asyncio.fixture
async def permissive_manager() -> PermissionManager:
    """Create a PermissionManager with default_deny=False."""
    return PermissionManager(default_deny=False)


# ============================================================================
# PermissionGrant Tests
# ============================================================================


class TestPermissionGrant:
    """Tests for the PermissionGrant class."""

    def test_grant_creation(self) -> None:
        """Test basic grant creation."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
            granted_by="admin",
            reason="Read access to data directory",
        )

        assert grant.id is not None
        assert grant.agent_id == "agent-1"
        assert grant.resource_pattern == "/data/*"
        assert grant.resource_type == ResourceType.FILE
        assert grant.level == PermissionLevel.READ
        assert grant.granted_by == "admin"
        assert grant.reason == "Read access to data directory"
        assert grant.expires_at is None
        assert grant.created_at is not None

    def test_grant_with_expiration(self) -> None:
        """Test grant with expiration time."""
        future = datetime.utcnow() + timedelta(hours=1)
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.API,
            level=PermissionLevel.EXECUTE,
            expires_at=future,
        )

        assert grant.expires_at == future
        assert grant.is_expired() is False

    def test_is_expired_no_expiration(self) -> None:
        """Test is_expired with no expiration set."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        assert grant.is_expired() is False

    def test_is_expired_future(self) -> None:
        """Test is_expired with future expiration."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
            expires_at=datetime.utcnow() + timedelta(hours=1),
        )

        assert grant.is_expired() is False

    def test_is_expired_past(self) -> None:
        """Test is_expired with past expiration."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
            expires_at=datetime.utcnow() - timedelta(hours=1),
        )

        assert grant.is_expired() is True

    def test_matches_exact(self) -> None:
        """Test matching with exact pattern."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="/data/file.txt",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        assert grant.matches("/data/file.txt", ResourceType.FILE) is True
        assert grant.matches("/data/other.txt", ResourceType.FILE) is False

    def test_matches_wildcard(self) -> None:
        """Test matching with wildcard pattern."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        assert grant.matches("/data/file.txt", ResourceType.FILE) is True
        # fnmatch's * matches everything including /
        assert grant.matches("/data/subdir/file.txt", ResourceType.FILE) is True
        assert grant.matches("/other/file.txt", ResourceType.FILE) is False

    def test_matches_recursive_wildcard(self) -> None:
        """Test matching with recursive pattern."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="/data/**",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        # fnmatch treats ** similar to * - both match everything including /
        assert grant.matches("/data/file.txt", ResourceType.FILE) is True
        assert grant.matches("/data/subdir/file.txt", ResourceType.FILE) is True

    def test_matches_wrong_resource_type(self) -> None:
        """Test matching fails with wrong resource type."""
        grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        # Same pattern but different resource type
        assert grant.matches("/data/table", ResourceType.DATABASE) is False

    def test_allows_hierarchy(self) -> None:
        """Test permission level hierarchy."""
        admin_grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.ADMIN,
        )

        # ADMIN allows all levels
        assert admin_grant.allows(PermissionLevel.NONE) is True
        assert admin_grant.allows(PermissionLevel.READ) is True
        assert admin_grant.allows(PermissionLevel.WRITE) is True
        assert admin_grant.allows(PermissionLevel.EXECUTE) is True
        assert admin_grant.allows(PermissionLevel.DELETE) is True
        assert admin_grant.allows(PermissionLevel.ADMIN) is True

    def test_allows_read_only(self) -> None:
        """Test READ grant only allows READ and NONE."""
        read_grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        assert read_grant.allows(PermissionLevel.NONE) is True
        assert read_grant.allows(PermissionLevel.READ) is True
        assert read_grant.allows(PermissionLevel.WRITE) is False
        assert read_grant.allows(PermissionLevel.EXECUTE) is False
        assert read_grant.allows(PermissionLevel.DELETE) is False
        assert read_grant.allows(PermissionLevel.ADMIN) is False

    def test_allows_write_includes_read(self) -> None:
        """Test WRITE grant includes READ."""
        write_grant = PermissionGrant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.WRITE,
        )

        assert write_grant.allows(PermissionLevel.READ) is True
        assert write_grant.allows(PermissionLevel.WRITE) is True
        assert write_grant.allows(PermissionLevel.EXECUTE) is False


# ============================================================================
# PermissionManager Tests
# ============================================================================


class TestPermissionManager:
    """Tests for the PermissionManager class."""

    @pytest.mark.asyncio
    async def test_grant_creates_permission(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test granting a permission."""
        grant = await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
            granted_by="admin",
            reason="Read access",
        )

        assert grant.id is not None
        assert grant.agent_id == "agent-1"
        assert grant.resource_pattern == "/data/*"

    @pytest.mark.asyncio
    async def test_grant_with_duration(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test granting a temporary permission."""
        grant = await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.API,
            level=PermissionLevel.EXECUTE,
            duration_seconds=3600,  # 1 hour
        )

        assert grant.expires_at is not None
        assert grant.is_expired() is False

    @pytest.mark.asyncio
    async def test_revoke_by_id(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test revoking a grant by ID."""
        grant = await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        success = await permission_manager.revoke(grant.id)
        assert success is True

        # Verify grant is removed
        grants = await permission_manager.list_grants(agent_id="agent-1")
        assert len(grants) == 0

    @pytest.mark.asyncio
    async def test_revoke_nonexistent(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test revoking a non-existent grant."""
        success = await permission_manager.revoke("nonexistent-id")
        assert success is False

    @pytest.mark.asyncio
    async def test_revoke_all_for_agent(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test revoking all permissions for an agent."""
        # Grant multiple permissions
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/api/*",
            resource_type=ResourceType.API,
            level=PermissionLevel.EXECUTE,
        )
        await permission_manager.grant(
            agent_id="agent-2",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        revoked = await permission_manager.revoke_all("agent-1")
        assert revoked == 2

        # Verify agent-1 grants are gone
        grants = await permission_manager.list_grants(agent_id="agent-1")
        assert len(grants) == 0

        # Verify agent-2 grant remains
        grants = await permission_manager.list_grants(agent_id="agent-2")
        assert len(grants) == 1

    @pytest.mark.asyncio
    async def test_revoke_all_no_grants(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test revoking all when no grants exist."""
        revoked = await permission_manager.revoke_all("nonexistent-agent")
        assert revoked == 0

    @pytest.mark.asyncio
    async def test_check_granted(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test checking a granted permission."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        allowed = await permission_manager.check(
            agent_id="agent-1",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.READ,
        )

        assert allowed is True

    @pytest.mark.asyncio
    async def test_check_denied_default_deny(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test checking denied with default_deny=True."""
        # No grants, should be denied
        allowed = await permission_manager.check(
            agent_id="agent-1",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.READ,
        )

        assert allowed is False

    @pytest.mark.asyncio
    async def test_check_uses_default_permissions(
        self,
        permissive_manager: PermissionManager,
    ) -> None:
        """Test that default permissions apply when default_deny=False."""
        # No explicit grants, but FILE default is READ
        allowed = await permissive_manager.check(
            agent_id="agent-1",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.READ,
        )

        assert allowed is True

        # But WRITE should fail
        allowed = await permissive_manager.check(
            agent_id="agent-1",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.WRITE,
        )

        assert allowed is False

    @pytest.mark.asyncio
    async def test_check_shell_denied_by_default(
        self,
        permissive_manager: PermissionManager,
    ) -> None:
        """Test SHELL is denied by default (NONE level)."""
        allowed = await permissive_manager.check(
            agent_id="agent-1",
            resource="rm -rf /",
            resource_type=ResourceType.SHELL,
            required_level=PermissionLevel.EXECUTE,
        )

        assert allowed is False

    @pytest.mark.asyncio
    async def test_check_expired_grant_ignored(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test that expired grants are ignored in checks."""
        # Create an already-expired grant
        grant = await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
            duration_seconds=1,  # Very short
        )

        # Manually expire it
        grant.expires_at = datetime.utcnow() - timedelta(seconds=10)

        allowed = await permission_manager.check(
            agent_id="agent-1",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.READ,
        )

        assert allowed is False

    @pytest.mark.asyncio
    async def test_check_insufficient_level(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test check fails when grant level is insufficient."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        # Try to get WRITE access with only READ grant
        allowed = await permission_manager.check(
            agent_id="agent-1",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.WRITE,
        )

        assert allowed is False

    @pytest.mark.asyncio
    async def test_check_action_file_read(
        self,
        permission_manager: PermissionManager,
        action_metadata: ActionMetadata,
    ) -> None:
        """Test check_action for file read."""
        await permission_manager.grant(
            agent_id="test-agent",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        action = ActionRequest(
            action_type=ActionType.FILE_READ,
            resource="/data/file.txt",
            metadata=action_metadata,
        )

        allowed = await permission_manager.check_action(action)
        assert allowed is True

    @pytest.mark.asyncio
    async def test_check_action_file_write(
        self,
        permission_manager: PermissionManager,
        action_metadata: ActionMetadata,
    ) -> None:
        """Test check_action for file write."""
        await permission_manager.grant(
            agent_id="test-agent",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.WRITE,
        )

        action = ActionRequest(
            action_type=ActionType.FILE_WRITE,
            resource="/data/file.txt",
            metadata=action_metadata,
        )

        allowed = await permission_manager.check_action(action)
        assert allowed is True

    @pytest.mark.asyncio
    async def test_check_action_uses_tool_name_as_resource(
        self,
        permission_manager: PermissionManager,
        action_metadata: ActionMetadata,
    ) -> None:
        """Test check_action uses tool_name when resource is None."""
        await permission_manager.grant(
            agent_id="test-agent",
            resource_pattern="search_*",
            resource_type=ResourceType.CUSTOM,
            level=PermissionLevel.EXECUTE,
        )

        action = ActionRequest(
            action_type=ActionType.TOOL_CALL,
            tool_name="search_documents",
            resource=None,
            metadata=action_metadata,
        )

        allowed = await permission_manager.check_action(action)
        assert allowed is True

    @pytest.mark.asyncio
    async def test_require_permission_granted(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test require_permission doesn't raise when granted."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        # Should not raise
        await permission_manager.require_permission(
            agent_id="agent-1",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.READ,
        )

    @pytest.mark.asyncio
    async def test_require_permission_denied(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test require_permission raises when denied."""
        with pytest.raises(PermissionDeniedError) as exc_info:
            await permission_manager.require_permission(
                agent_id="agent-1",
                resource="/secret/file.txt",
                resource_type=ResourceType.FILE,
                required_level=PermissionLevel.READ,
            )

        assert "/secret/file.txt" in str(exc_info.value)
        assert exc_info.value.agent_id == "agent-1"
        assert exc_info.value.required_permission == "read"

    @pytest.mark.asyncio
    async def test_list_grants_all(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test listing all grants."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )
        await permission_manager.grant(
            agent_id="agent-2",
            resource_pattern="/api/*",
            resource_type=ResourceType.API,
            level=PermissionLevel.EXECUTE,
        )

        grants = await permission_manager.list_grants()
        assert len(grants) == 2

    @pytest.mark.asyncio
    async def test_list_grants_by_agent(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test listing grants filtered by agent."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )
        await permission_manager.grant(
            agent_id="agent-2",
            resource_pattern="/api/*",
            resource_type=ResourceType.API,
            level=PermissionLevel.EXECUTE,
        )

        grants = await permission_manager.list_grants(agent_id="agent-1")
        assert len(grants) == 1
        assert grants[0].agent_id == "agent-1"

    @pytest.mark.asyncio
    async def test_list_grants_by_resource_type(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test listing grants filtered by resource type."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/api/*",
            resource_type=ResourceType.API,
            level=PermissionLevel.EXECUTE,
        )

        grants = await permission_manager.list_grants(resource_type=ResourceType.FILE)
        assert len(grants) == 1
        assert grants[0].resource_type == ResourceType.FILE

    @pytest.mark.asyncio
    async def test_list_grants_excludes_expired(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test that list_grants excludes expired grants."""
        # Create expired grant
        grant = await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/old/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
            duration_seconds=1,
        )
        grant.expires_at = datetime.utcnow() - timedelta(seconds=10)

        # Create valid grant
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/new/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        grants = await permission_manager.list_grants()
        assert len(grants) == 1
        assert grants[0].resource_pattern == "/new/*"

    def test_set_default_permission(
        self,
    ) -> None:
        """Test setting default permission level."""
        manager = PermissionManager(default_deny=False)

        # Default for SHELL is NONE
        assert manager._default_permissions[ResourceType.SHELL] == PermissionLevel.NONE

        # Change it
        manager.set_default_permission(ResourceType.SHELL, PermissionLevel.EXECUTE)
        assert (
            manager._default_permissions[ResourceType.SHELL] == PermissionLevel.EXECUTE
        )

    @pytest.mark.asyncio
    async def test_set_default_permission_affects_checks(
        self,
        permissive_manager: PermissionManager,
    ) -> None:
        """Test that changing default permissions affects checks."""
        # Initially SHELL is NONE
        allowed = await permissive_manager.check(
            agent_id="agent-1",
            resource="ls",
            resource_type=ResourceType.SHELL,
            required_level=PermissionLevel.EXECUTE,
        )
        assert allowed is False

        # Change default
        permissive_manager.set_default_permission(
            ResourceType.SHELL, PermissionLevel.EXECUTE
        )

        # Now should be allowed
        allowed = await permissive_manager.check(
            agent_id="agent-1",
            resource="ls",
            resource_type=ResourceType.SHELL,
            required_level=PermissionLevel.EXECUTE,
        )
        assert allowed is True


# ============================================================================
# Edge Cases
# ============================================================================


class TestPermissionEdgeCases:
    """Edge cases that could reveal hidden bugs."""

    @pytest.mark.asyncio
    async def test_multiple_matching_grants(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test when multiple grants match - first sufficient one wins."""
        # Grant READ on all files
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        # Also grant WRITE on specific path
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/writable/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.WRITE,
        )

        # Write on writable path should work
        allowed = await permission_manager.check(
            agent_id="agent-1",
            resource="/data/writable/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.WRITE,
        )
        assert allowed is True

    @pytest.mark.asyncio
    async def test_wildcard_all_pattern(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test * pattern matches everything."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.ADMIN,
        )

        allowed = await permission_manager.check(
            agent_id="agent-1",
            resource="/any/path/anywhere/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.DELETE,
        )

        # fnmatch's * matches everything including /
        assert allowed is True

    @pytest.mark.asyncio
    async def test_question_mark_wildcard(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test ? wildcard matches single character."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="file?.txt",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        assert (
            await permission_manager.check(
                agent_id="agent-1",
                resource="file1.txt",
                resource_type=ResourceType.FILE,
                required_level=PermissionLevel.READ,
            )
            is True
        )

        assert (
            await permission_manager.check(
                agent_id="agent-1",
                resource="file10.txt",  # Two characters, won't match
                resource_type=ResourceType.FILE,
                required_level=PermissionLevel.READ,
            )
            is False
        )

    @pytest.mark.asyncio
    async def test_concurrent_grant_revoke(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test concurrent grant and revoke operations."""

        async def grant_many():
            grants = []
            for i in range(10):
                g = await permission_manager.grant(
                    agent_id="agent-1",
                    resource_pattern=f"/path{i}/*",
                    resource_type=ResourceType.FILE,
                    level=PermissionLevel.READ,
                )
                grants.append(g)
            return grants

        async def revoke_many(grants):
            for g in grants:
                await permission_manager.revoke(g.id)

        grants = await grant_many()
        await revoke_many(grants)

        # All should be revoked
        remaining = await permission_manager.list_grants(agent_id="agent-1")
        assert len(remaining) == 0

    @pytest.mark.asyncio
    async def test_check_action_with_no_resource_or_tool(
        self,
        permission_manager: PermissionManager,
        action_metadata: ActionMetadata,
    ) -> None:
        """Test check_action when both resource and tool_name are None."""
        await permission_manager.grant(
            agent_id="test-agent",
            resource_pattern="*",
            resource_type=ResourceType.LLM,
            level=PermissionLevel.EXECUTE,
        )

        action = ActionRequest(
            action_type=ActionType.LLM_CALL,
            resource=None,
            tool_name=None,
            metadata=action_metadata,
        )

        # Should use "*" as fallback
        allowed = await permission_manager.check_action(action)
        assert allowed is True

    @pytest.mark.asyncio
    async def test_cleanup_expired_called_on_check(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test that expired grants are cleaned up during check."""
        # Create expired grant
        grant = await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/old/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
            duration_seconds=1,
        )
        grant.expires_at = datetime.utcnow() - timedelta(seconds=10)

        # Create valid grant
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/new/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        # Run a check - this should trigger cleanup
        await permission_manager.check(
            agent_id="agent-1",
            resource="/new/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.READ,
        )

        # Now verify expired grant was cleaned up
        async with permission_manager._lock:
            assert len(permission_manager._grants) == 1
            assert permission_manager._grants[0].resource_pattern == "/new/*"

    @pytest.mark.asyncio
    async def test_check_wrong_agent_id(
        self,
        permission_manager: PermissionManager,
    ) -> None:
        """Test check fails for different agent."""
        await permission_manager.grant(
            agent_id="agent-1",
            resource_pattern="/data/*",
            resource_type=ResourceType.FILE,
            level=PermissionLevel.READ,
        )

        # Different agent should not have access
        allowed = await permission_manager.check(
            agent_id="agent-2",
            resource="/data/file.txt",
            resource_type=ResourceType.FILE,
            required_level=PermissionLevel.READ,
        )

        assert allowed is False
