from __future__ import annotations

import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))

import pytest
from src.state_machine import (
    OrchestratorState,
    OrchestratorStateMachine,
    InvalidTransition,
    DEFAULT_TRANSITIONS,
    GLOBAL_TRANSITIONS,
)


class TestNewStatesExist:
    """Test that new states AWAITING_CONFIRM and EXECUTING_ACTIONS exist in the Enum."""

    def test_awaiting_confirm_state_exists(self):
        """Test that AWAITING_CONFIRM state is defined in OrchestratorState enum."""
        assert hasattr(OrchestratorState, "AWAITING_CONFIRM")
        assert OrchestratorState.AWAITING_CONFIRM.value == "AWAITING_CONFIRM"

    def test_executing_actions_state_exists(self):
        """Test that EXECUTING_ACTIONS state is defined in OrchestratorState enum."""
        assert hasattr(OrchestratorState, "EXECUTING_ACTIONS")
        assert OrchestratorState.EXECUTING_ACTIONS.value == "EXECUTING_ACTIONS"


class TestNewStateTransitions:
    """Test that new states have proper transitions configured."""

    def test_awaiting_confirm_in_default_transitions(self):
        """Test that AWAITING_CONFIRM has transitions defined in DEFAULT_TRANSITIONS."""
        assert OrchestratorState.AWAITING_CONFIRM in DEFAULT_TRANSITIONS
        transitions = DEFAULT_TRANSITIONS[OrchestratorState.AWAITING_CONFIRM]
        assert isinstance(transitions, dict)
        assert len(transitions) > 0

    def test_executing_actions_in_default_transitions(self):
        """Test that EXECUTING_ACTIONS has transitions defined in DEFAULT_TRANSITIONS."""
        assert OrchestratorState.EXECUTING_ACTIONS in DEFAULT_TRANSITIONS
        transitions = DEFAULT_TRANSITIONS[OrchestratorState.EXECUTING_ACTIONS]
        assert isinstance(transitions, dict)
        assert len(transitions) > 0

    def test_processing_llm_response_to_awaiting_confirm(self):
        """Test that PROCESSING state transitions to AWAITING_CONFIRM on 'llm_response' event."""
        transitions = DEFAULT_TRANSITIONS.get(OrchestratorState.PROCESSING, {})
        assert "llm_response" in transitions
        assert transitions["llm_response"] == OrchestratorState.AWAITING_CONFIRM

    def test_awaiting_confirm_user_confirmed_to_executing_actions(self):
        """Test that AWAITING_CONFIRM transitions to EXECUTING_ACTIONS on 'user_confirmed' event."""
        transitions = DEFAULT_TRANSITIONS.get(OrchestratorState.AWAITING_CONFIRM, {})
        assert "user_confirmed" in transitions
        assert transitions["user_confirmed"] == OrchestratorState.EXECUTING_ACTIONS

    def test_awaiting_confirm_user_rejected_to_idle(self):
        """Test that AWAITING_CONFIRM transitions to IDLE on 'user_rejected' event."""
        transitions = DEFAULT_TRANSITIONS.get(OrchestratorState.AWAITING_CONFIRM, {})
        assert "user_rejected" in transitions
        assert transitions["user_rejected"] == OrchestratorState.IDLE

    def test_executing_actions_events(self):
        """Test that EXECUTING_ACTIONS has 'actions_complete' and 'actions_failed' events."""
        transitions = DEFAULT_TRANSITIONS.get(OrchestratorState.EXECUTING_ACTIONS, {})
        assert "actions_complete" in transitions
        assert "actions_failed" in transitions
        assert transitions["actions_complete"] == OrchestratorState.SPEAKING
        assert transitions["actions_failed"] == OrchestratorState.SPEAKING


class TestStateMachineWithNewStates:
    """Test state machine operations with the new states."""

    def test_transition_to_awaiting_confirm(self):
        """Test that state machine can transition to AWAITING_CONFIRM state via 'llm_response' event."""
        sm = OrchestratorStateMachine()
        sm._state = OrchestratorState.PROCESSING
        new_state = sm.handle_event("llm_response")
        assert new_state == OrchestratorState.AWAITING_CONFIRM
        assert sm.state == OrchestratorState.AWAITING_CONFIRM

    def test_transition_from_awaiting_confirm_to_executing_actions(self):
        """Test transition from AWAITING_CONFIRM to EXECUTING_ACTIONS via 'user_confirmed' event."""
        sm = OrchestratorStateMachine()
        sm._state = OrchestratorState.AWAITING_CONFIRM
        new_state = sm.handle_event("user_confirmed")
        assert new_state == OrchestratorState.EXECUTING_ACTIONS
        assert sm.state == OrchestratorState.EXECUTING_ACTIONS

    def test_transition_from_awaiting_confirm_to_idle_on_reject(self):
        """Test transition from AWAITING_CONFIRM to IDLE via 'user_rejected' event."""
        sm = OrchestratorStateMachine()
        sm._state = OrchestratorState.AWAITING_CONFIRM
        new_state = sm.handle_event("user_rejected")
        assert new_state == OrchestratorState.IDLE
        assert sm.state == OrchestratorState.IDLE

    def test_executing_actions_complete_to_speaking(self):
        """Test that EXECUTING_ACTIONS transitions to SPEAKING on 'actions_complete' event."""
        sm = OrchestratorStateMachine()
        sm._state = OrchestratorState.EXECUTING_ACTIONS
        new_state = sm.handle_event("actions_complete")
        assert new_state == OrchestratorState.SPEAKING
        assert sm.state == OrchestratorState.SPEAKING

    def test_executing_actions_failed_to_speaking(self):
        """Test that EXECUTING_ACTIONS transitions to SPEAKING on 'actions_failed' event."""
        sm = OrchestratorStateMachine()
        sm._state = OrchestratorState.EXECUTING_ACTIONS
        new_state = sm.handle_event("actions_failed")
        assert new_state == OrchestratorState.SPEAKING
        assert sm.state == OrchestratorState.SPEAKING
