"""
Tests for actions:
- SetSecretAction
- ManageSecretAction
- UpdateSettingsAction
"""

import pytest
from unittest.mock import AsyncMock, MagicMock

from elizaos_plugin_secrets_manager.types import SecretLevel, SecretContext


# ============================================================================
# SetSecretAction Tests
# ============================================================================


class TestSetSecretAction:
    @pytest.fixture
    def action(self):
        from elizaos_plugin_secrets_manager.actions.set_secret import SetSecretAction
        return SetSecretAction()

    def test_name(self, action):
        assert action.name == "SET_SECRET"

    def test_has_description(self, action):
        assert action.description
        assert len(action.description) > 0

    def test_has_examples(self, action):
        assert action.examples
        assert len(action.examples) > 0


class TestManageSecretAction:
    @pytest.fixture
    def action(self):
        from elizaos_plugin_secrets_manager.actions.manage_secret import ManageSecretAction
        return ManageSecretAction()

    def test_name(self, action):
        assert action.name == "MANAGE_SECRET"

    def test_has_description(self, action):
        assert action.description
        assert len(action.description) > 0

    def test_has_examples(self, action):
        assert action.examples
        assert len(action.examples) > 0


# ============================================================================
# UpdateSettingsAction Tests
# ============================================================================


class TestUpdateSettingsAction:
    @pytest.fixture
    def action(self):
        from elizaos_plugin_secrets_manager.actions.update_settings import UpdateSettingsAction
        return UpdateSettingsAction()

    def test_name(self, action):
        assert action.name == "UPDATE_SETTINGS"

    def test_has_description(self, action):
        assert action.description
        assert len(action.description) > 0

    def test_has_examples(self, action):
        assert action.examples
        assert len(action.examples) > 0

    @pytest.mark.asyncio
    async def test_validate_rejects_non_dm(self, action):
        runtime = MagicMock()
        msg = MagicMock()
        msg.content = {"channelType": "CHANNEL"}
        result = await action.validate(runtime, msg)
        assert result is False

    @pytest.mark.asyncio
    async def test_validate_rejects_no_room(self, action):
        runtime = MagicMock()
        runtime.get_room = AsyncMock(return_value=None)
        msg = MagicMock()
        msg.room_id = "room-1"
        msg.content = {"channelType": "DM"}
        result = await action.validate(runtime, msg)
        assert result is False

    @pytest.mark.asyncio
    async def test_validate_accepts_dm_with_unconfigured(self, action):
        runtime = MagicMock()
        room = MagicMock()
        room.world_id = "world-1"
        runtime.get_room = AsyncMock(return_value=room)

        world = MagicMock()
        world.metadata = {
            "settings": {
                "OPENAI_API_KEY": {
                    "name": "OpenAI Key",
                    "required": True,
                    "value": None,
                },
            }
        }
        runtime.get_world = AsyncMock(return_value=world)

        msg = MagicMock()
        msg.room_id = "room-1"
        msg.content = {"channelType": "DM"}
        result = await action.validate(runtime, msg)
        assert result is True

    @pytest.mark.asyncio
    async def test_validate_rejects_when_all_configured(self, action):
        runtime = MagicMock()
        room = MagicMock()
        room.world_id = "world-1"
        runtime.get_room = AsyncMock(return_value=room)

        world = MagicMock()
        world.metadata = {
            "settings": {
                "OPENAI_API_KEY": {
                    "name": "OpenAI Key",
                    "required": True,
                    "value": "sk-set",
                },
            }
        }
        runtime.get_world = AsyncMock(return_value=world)

        msg = MagicMock()
        msg.room_id = "room-1"
        msg.content = {"channelType": "DM"}
        result = await action.validate(runtime, msg)
        assert result is False

    @pytest.mark.asyncio
    async def test_handler_no_room(self, action):
        runtime = MagicMock()
        runtime.get_room = AsyncMock(return_value=None)

        msg = MagicMock()
        msg.room_id = "room-1"
        msg.content = {"text": "My key is sk-abc123"}

        result = await action.handler(runtime, msg, {"text": "My key is sk-abc123"})
        assert result["success"] is False

    @pytest.mark.asyncio
    async def test_handler_no_settings(self, action):
        runtime = MagicMock()
        room = MagicMock()
        room.world_id = "world-1"
        runtime.get_room = AsyncMock(return_value=room)

        world = MagicMock()
        world.metadata = {}
        runtime.get_world = AsyncMock(return_value=world)

        msg = MagicMock()
        msg.room_id = "room-1"
        msg.content = {"text": "test"}

        result = await action.handler(runtime, msg, {"text": "test"})
        assert result["success"] is False

    @pytest.mark.asyncio
    async def test_handler_extracts_settings_with_pattern(self, action):
        runtime = MagicMock()
        runtime.agent_id = "test-agent"
        room = MagicMock()
        room.world_id = "world-1"
        runtime.get_room = AsyncMock(return_value=room)

        settings = {
            "OPENAI_API_KEY": {
                "name": "OpenAI Key",
                "description": "OpenAI API key",
                "required": True,
                "value": None,
                "secret": True,
            },
        }
        world = MagicMock()
        world.metadata = {"settings": settings}
        runtime.get_world = AsyncMock(return_value=world)
        runtime.update_world = AsyncMock()
        runtime.get_service = MagicMock(return_value=None)
        runtime.generate_text = AsyncMock(return_value='[]')

        msg = MagicMock()
        msg.room_id = "room-1"
        msg.content = {"text": "OPENAI_API_KEY = sk-abc123def456ghi789jkl"}

        result = await action.handler(
            runtime, msg,
            {"text": "OPENAI_API_KEY = sk-abc123def456ghi789jkl"}
        )
        # The action should have attempted to extract and process settings
        assert isinstance(result, dict)


# ============================================================================
# Action Instances Tests
# ============================================================================


class TestActionInstances:
    def test_all_actions_importable(self):
        from elizaos_plugin_secrets_manager.actions import (
            set_secret_action,
            manage_secret_action,
            update_settings_action,
        )
        assert set_secret_action is not None
        assert manage_secret_action is not None
        assert update_settings_action is not None

    def test_action_names(self):
        from elizaos_plugin_secrets_manager.actions import (
            set_secret_action,
            manage_secret_action,
            update_settings_action,
        )
        assert set_secret_action.name == "SET_SECRET"
        assert manage_secret_action.name == "MANAGE_SECRET"
        assert update_settings_action.name == "UPDATE_SETTINGS"
