"""Tests for state management."""

from __future__ import annotations

from typing import TYPE_CHECKING

from curadise_agent.state.manager import AgentState, StateManager

if TYPE_CHECKING:
    from pathlib import Path

    from curadise_agent.state.storage import StateStorage


class TestStateStorage:
    """Tests for StateStorage."""

    def test_agent_id_operations(self, state_storage: StateStorage) -> None:
        """Test agent ID save/get/delete."""
        # Initially None
        assert state_storage.get_agent_id() is None

        # Save and retrieve
        state_storage.save_agent_id("agent-123")
        assert state_storage.get_agent_id() == "agent-123"

        # Delete
        deleted = state_storage.delete_agent_id()
        assert deleted
        assert state_storage.get_agent_id() is None

        # Delete when not exists
        deleted = state_storage.delete_agent_id()
        assert not deleted

    def test_token_operations(self, state_storage: StateStorage) -> None:
        """Test token save/get/delete."""
        # Initially None
        assert state_storage.get_token() is None

        # Save and retrieve
        state_storage.save_token("secret-token")
        assert state_storage.get_token() == "secret-token"

        # Delete
        deleted = state_storage.delete_token()
        assert deleted
        assert state_storage.get_token() is None

    def test_generic_key_value(self, state_storage: StateStorage) -> None:
        """Test generic key-value operations."""
        # Set and get
        state_storage.set("config", {"key": "value"})
        data = state_storage.get("config")
        assert data == {"key": "value"}

        # Exists check
        assert state_storage.exists("config")
        assert not state_storage.exists("nonexistent")

        # Delete
        deleted = state_storage.delete("config")
        assert deleted
        assert not state_storage.exists("config")

    def test_list_keys(self, state_storage: StateStorage) -> None:
        """Test listing stored keys."""
        state_storage.set("key1", {"a": 1})
        state_storage.set("key2", {"b": 2})
        state_storage.set("key3", {"c": 3})

        keys = state_storage.list_keys()
        assert sorted(keys) == ["key1", "key2", "key3"]

    def test_clear_all(self, state_storage: StateStorage) -> None:
        """Test clearing all stored data."""
        state_storage.save_agent_id("agent-123")
        state_storage.save_token("token")
        state_storage.set("config", {"key": "value"})

        count = state_storage.clear_all()
        assert count == 3

        assert state_storage.get_agent_id() is None
        assert state_storage.get_token() is None
        assert state_storage.get("config") is None

    def test_file_permissions(self, state_storage: StateStorage, temp_dir: Path) -> None:
        """Test that files are created with secure permissions."""
        state_storage.save_token("secret")

        token_file = temp_dir / "token"
        assert token_file.exists()

        # Check permissions (Unix only)
        import platform

        if platform.system() != "Windows":
            mode = token_file.stat().st_mode
            # Should be 0o600 (owner read/write only)
            assert mode & 0o077 == 0  # No group/other permissions


class TestStateManager:
    """Tests for StateManager."""

    async def test_initial_state(self, state_manager: StateManager) -> None:
        """Test initial state values."""
        assert state_manager.state == AgentState.INITIALIZING
        assert state_manager.agent_id is None
        assert state_manager.token is None
        assert not state_manager.is_registered
        assert not state_manager.is_authenticated

    async def test_state_transitions(self, state_manager: StateManager) -> None:
        """Test state transitions."""
        state_manager.transition_to(AgentState.REGISTERING)
        assert state_manager.state == AgentState.REGISTERING

        state_manager.transition_to(AgentState.RUNNING)
        assert state_manager.state == AgentState.RUNNING
        assert state_manager.is_running

        state_manager.transition_to(AgentState.SHUTTING_DOWN)
        assert state_manager.state == AgentState.SHUTTING_DOWN
        assert not state_manager.is_running

    async def test_set_credentials(self, state_manager: StateManager) -> None:
        """Test setting agent credentials."""
        state_manager.set_agent_id("agent-123")
        state_manager.set_token("secret-token")

        assert state_manager.agent_id == "agent-123"
        assert state_manager.token == "secret-token"
        assert state_manager.is_registered
        assert state_manager.is_authenticated

    async def test_clear_credentials(self, state_manager: StateManager) -> None:
        """Test clearing credentials."""
        state_manager.set_agent_id("agent-123")
        state_manager.set_token("secret-token")

        state_manager.clear_credentials()

        assert state_manager.agent_id is None
        assert state_manager.token is None
        assert not state_manager.is_registered

    async def test_load_persisted_state(
        self, state_storage: StateStorage, state_manager: StateManager
    ) -> None:
        """Test loading persisted state."""
        # Save state directly to storage
        state_storage.save_agent_id("persisted-agent")
        state_storage.save_token("persisted-token")

        # Create new manager and load
        new_manager = StateManager(storage=state_storage)
        await new_manager.load()

        assert new_manager.agent_id == "persisted-agent"
        assert new_manager.token == "persisted-token"

    async def test_get_status(self, state_manager: StateManager) -> None:
        """Test status reporting."""
        state_manager.set_agent_id("agent-123")
        state_manager.transition_to(AgentState.RUNNING)

        status = state_manager.get_status()

        assert status["state"] == "running"
        assert status["agent_id"] == "agent-123"
        assert status["is_registered"]

    async def test_metadata(self, state_manager: StateManager) -> None:
        """Test metadata operations."""
        state_manager.set_metadata("version", "1.0.0")
        state_manager.set_metadata("custom", {"key": "value"})

        assert state_manager.get_metadata("version") == "1.0.0"
        assert state_manager.get_metadata("custom") == {"key": "value"}
        assert state_manager.get_metadata("nonexistent", "default") == "default"
