"""Tests for the process action module."""

from __future__ import annotations

import pytest

from elizaos_plugin_shell.actions.process_action import (
    ProcessAction,
    ProcessActionParams,
    ProcessActionResult,
)
from elizaos_plugin_shell.process_registry import (
    ProcessRegistry,
    ProcessSession,
    ProcessStatus,
)


class TestProcessAction:
    def setup_method(self):
        self.registry = ProcessRegistry()
        self.action = ProcessAction(self.registry)

    def teardown_method(self):
        self.registry.reset_for_tests()

    def test_validate_process_keyword(self):
        msg = {"content": {"text": "list all running processes"}}
        assert self.action.validate(msg) is True

    def test_validate_session_keyword(self):
        msg = {"content": {"text": "show me the session status"}}
        assert self.action.validate(msg) is True

    def test_validate_no_match(self):
        msg = {"content": {"text": "what is the weather?"}}
        assert self.action.validate(msg) is False

    @pytest.mark.asyncio
    async def test_list_empty(self):
        params = ProcessActionParams(action="list")
        result = await self.action.handler(params)
        assert result.success is True
        assert "No active" in result.message

    @pytest.mark.asyncio
    async def test_list_with_sessions(self):
        session = ProcessSession(
            id="test-1", command="echo hello", backgrounded=True
        )
        self.registry.register_process(session)

        params = ProcessActionParams(action="list")
        result = await self.action.handler(params)
        assert result.success is True
        assert "test-1" in result.message

    @pytest.mark.asyncio
    async def test_poll_session(self):
        session = ProcessSession(
            id="test-1", command="echo hello", backgrounded=True
        )
        self.registry.register_process(session)
        self.registry.append_output(session, "stdout", "hello world")

        params = ProcessActionParams(action="poll", session_id="test-1")
        result = await self.action.handler(params)
        assert result.success is True
        assert "test-1" in result.message

    @pytest.mark.asyncio
    async def test_poll_nonexistent(self):
        params = ProcessActionParams(action="poll", session_id="nonexistent")
        result = await self.action.handler(params)
        assert result.success is False

    @pytest.mark.asyncio
    async def test_poll_finished_session(self):
        session = ProcessSession(
            id="test-1", command="echo hello", backgrounded=True
        )
        self.registry.register_process(session)
        self.registry.mark_exited(session, 0, None, ProcessStatus.COMPLETED)

        params = ProcessActionParams(action="poll", session_id="test-1")
        result = await self.action.handler(params)
        assert result.success is True
        assert "finished" in result.message.lower()

    @pytest.mark.asyncio
    async def test_log_session(self):
        session = ProcessSession(id="test-1", command="echo hello")
        self.registry.register_process(session)
        self.registry.append_output(session, "stdout", "line1\nline2\nline3\n")

        params = ProcessActionParams(
            action="log", session_id="test-1", offset=0, limit=2
        )
        result = await self.action.handler(params)
        assert result.success is True

    @pytest.mark.asyncio
    async def test_kill_session_no_pid(self):
        session = ProcessSession(id="test-1", command="cmd", pid=None)
        self.registry.register_process(session)

        params = ProcessActionParams(action="kill", session_id="test-1")
        result = await self.action.handler(params)
        assert result.success is False

    @pytest.mark.asyncio
    async def test_kill_nonexistent(self):
        params = ProcessActionParams(action="kill", session_id="nonexistent")
        result = await self.action.handler(params)
        assert result.success is False

    @pytest.mark.asyncio
    async def test_clear_finished(self):
        params = ProcessActionParams(action="clear")
        result = await self.action.handler(params)
        assert result.success is True

    @pytest.mark.asyncio
    async def test_remove_session(self):
        session = ProcessSession(id="test-1", command="cmd")
        self.registry.register_process(session)

        params = ProcessActionParams(action="remove", session_id="test-1")
        result = await self.action.handler(params)
        assert result.success is True
        assert self.registry.get_process("test-1") is None

    @pytest.mark.asyncio
    async def test_write_action(self):
        session = ProcessSession(id="test-1", command="cmd")
        self.registry.register_process(session)

        params = ProcessActionParams(
            action="write", session_id="test-1", data="hello"
        )
        result = await self.action.handler(params)
        assert result.success is True

    @pytest.mark.asyncio
    async def test_write_exited_session(self):
        session = ProcessSession(id="test-1", command="cmd", exited=True)
        self.registry.register_process(session)

        params = ProcessActionParams(
            action="write", session_id="test-1", data="hello"
        )
        result = await self.action.handler(params)
        assert result.success is False

    @pytest.mark.asyncio
    async def test_unknown_action(self):
        params = ProcessActionParams(action="unknown")
        result = await self.action.handler(params)
        assert result.success is False

    @pytest.mark.asyncio
    async def test_missing_session_id(self):
        params = ProcessActionParams(action="poll")
        result = await self.action.handler(params)
        assert result.success is False

    def test_examples(self):
        examples = self.action.examples()
        assert len(examples) > 0
