"""Tests for FloorManager."""

import pytest

from thetable_poc.core import ParticipantFactory, Role
from thetable_poc.meeting import FloorManager


class TestFloorManager:
    """Test floor manager."""

    def test_initial_state(self):
        """Test initial state."""
        manager = FloorManager()
        assert manager.current_speaker is None
        assert manager.user_has_floor is False
        assert manager.has_pending_speakers() is False

    def test_grant_floor(self):
        """Test granting floor to participant."""
        manager = FloorManager()
        participant = ParticipantFactory.create_ai("Agent", Role.HOST)

        manager.grant_floor(participant)
        assert manager.current_speaker == participant
        assert manager.user_has_floor is False

    def test_grant_floor_to_user(self):
        """Test granting floor to human user."""
        manager = FloorManager()
        user = ParticipantFactory.create_human("User", Role.MEMBER)

        manager.grant_floor(user)
        assert manager.current_speaker == user
        assert manager.user_has_floor is True

    def test_release_floor(self):
        """Test releasing floor."""
        manager = FloorManager()
        participant = ParticipantFactory.create_ai("Agent", Role.HOST)

        manager.grant_floor(participant)
        manager.release_floor()

        assert manager.current_speaker is None
        assert manager.user_has_floor is False

    def test_request_floor(self):
        """Test requesting floor."""
        manager = FloorManager()
        p1 = ParticipantFactory.create_ai("Agent1", Role.HOST)
        p2 = ParticipantFactory.create_ai("Agent2", Role.PM)

        manager.request_floor(p1)
        manager.request_floor(p2)

        assert manager.has_pending_speakers() is True

    def test_request_floor_no_duplicates(self):
        """Test that same participant is not added twice to queue."""
        manager = FloorManager()
        participant = ParticipantFactory.create_ai("Agent", Role.HOST)

        manager.request_floor(participant)
        manager.request_floor(participant)

        # Should only be in queue once
        speaker1 = manager.get_next_speaker()
        speaker2 = manager.get_next_speaker()

        assert speaker1 == participant
        assert speaker2 is None

    def test_get_next_speaker(self):
        """Test getting next speaker from queue."""
        manager = FloorManager()
        p1 = ParticipantFactory.create_ai("Agent1", Role.HOST)
        p2 = ParticipantFactory.create_ai("Agent2", Role.PM)

        manager.request_floor(p1)
        manager.request_floor(p2)

        assert manager.get_next_speaker() == p1
        assert manager.get_next_speaker() == p2
        assert manager.get_next_speaker() is None

    def test_clear_queue(self):
        """Test clearing speaker queue."""
        manager = FloorManager()
        p1 = ParticipantFactory.create_ai("Agent1", Role.HOST)
        p2 = ParticipantFactory.create_ai("Agent2", Role.PM)

        manager.request_floor(p1)
        manager.request_floor(p2)
        manager.clear_queue()

        assert manager.has_pending_speakers() is False

    def test_interrupt_for_user(self):
        """Test interrupting for user input."""
        manager = FloorManager()
        participant = ParticipantFactory.create_ai("Agent", Role.HOST)

        manager.grant_floor(participant)
        manager.interrupt_for_user()

        assert manager.user_has_floor is True

    def test_can_speak_user_always(self):
        """Test that user can always speak."""
        manager = FloorManager()
        user = ParticipantFactory.create_human("User", Role.MEMBER)
        agent = ParticipantFactory.create_ai("Agent", Role.HOST)

        # User can speak when no one has floor
        assert manager.can_speak(user) is True

        # User can speak even when agent has floor
        manager.grant_floor(agent)
        assert manager.can_speak(user) is True

        # User can speak when user has floor
        manager.interrupt_for_user()
        assert manager.can_speak(user) is True

    def test_can_speak_ai_rules(self):
        """Test AI speaking rules."""
        manager = FloorManager()
        user = ParticipantFactory.create_human("User", Role.MEMBER)
        agent1 = ParticipantFactory.create_ai("Agent1", Role.HOST)
        agent2 = ParticipantFactory.create_ai("Agent2", Role.PM)

        # AI can speak when no one has floor
        assert manager.can_speak(agent1) is True

        # AI cannot speak when user has floor
        manager.grant_floor(user)
        assert manager.can_speak(agent1) is False

        # AI can speak when they have the floor
        manager.release_floor()
        manager.grant_floor(agent1)
        assert manager.can_speak(agent1) is True

        # Other AI cannot speak when someone else has floor
        assert manager.can_speak(agent2) is False

    def test_select_next_responder_by_name(self):
        """Test selecting responder by name mention."""
        manager = FloorManager()
        host = ParticipantFactory.create_ai("Alex", Role.HOST)
        pm = ParticipantFactory.create_ai("Sarah", Role.PM)
        participants = [host, pm]

        context = {"last_message": "Hey Sarah, what do you think?"}
        selected = manager.select_next_responder(participants, context)

        assert selected == pm

    def test_select_next_responder_from_queue(self):
        """Test selecting responder from queue."""
        manager = FloorManager()
        host = ParticipantFactory.create_ai("Alex", Role.HOST)
        pm = ParticipantFactory.create_ai("Sarah", Role.PM)
        participants = [host, pm]

        manager.request_floor(pm)
        context = {"last_message": "Any thoughts?"}
        selected = manager.select_next_responder(participants, context)

        assert selected == pm

    def test_select_next_responder_by_phase_opening(self):
        """Test phase-based selection for opening."""
        manager = FloorManager()
        host = ParticipantFactory.create_ai("Alex", Role.HOST)
        pm = ParticipantFactory.create_ai("Sarah", Role.PM)
        participants = [host, pm]

        context = {"phase": "opening", "last_message": ""}
        selected = manager.select_next_responder(participants, context)

        assert selected == host

    def test_select_next_responder_by_phase_status(self):
        """Test phase-based selection for status check."""
        manager = FloorManager()
        host = ParticipantFactory.create_ai("Alex", Role.HOST)
        pm = ParticipantFactory.create_ai("Sarah", Role.PM)
        participants = [host, pm]

        context = {"phase": "status_check", "last_message": ""}
        selected = manager.select_next_responder(participants, context)

        assert selected == pm

    def test_select_next_responder_by_phase_issue(self):
        """Test phase-based selection for issue resolution."""
        manager = FloorManager()
        host = ParticipantFactory.create_ai("Alex", Role.HOST)
        tech_lead = ParticipantFactory.create_ai("Mike", Role.TECH_LEAD)
        participants = [host, tech_lead]

        context = {"phase": "issue_resolution", "last_message": ""}
        selected = manager.select_next_responder(participants, context)

        assert selected == tech_lead

    def test_select_next_responder_priority(self):
        """Test responder selection priority: name > queue > phase."""
        manager = FloorManager()
        host = ParticipantFactory.create_ai("Alex", Role.HOST)
        pm = ParticipantFactory.create_ai("Sarah", Role.PM)
        participants = [host, pm]

        # Even with PM in queue and opening phase (which prefers host),
        # name mention takes priority
        manager.request_floor(pm)
        context = {"phase": "opening", "last_message": "Alex, your thoughts?"}
        selected = manager.select_next_responder(participants, context)

        assert selected == host


class TestFloorManagerDialogueMode:
    """Test dialogue mode functionality."""

    def test_initial_dialogue_state(self):
        """Test initial dialogue mode state."""
        manager = FloorManager()
        
        assert manager.in_dialogue_mode is False
        assert manager.dialogue_initiator is None

    def test_enter_dialogue_mode(self):
        """Test entering dialogue mode."""
        manager = FloorManager()
        human = ParticipantFactory.create_human("User", Role.MEMBER)
        
        manager.enter_dialogue_mode(human)
        
        assert manager.in_dialogue_mode is True
        assert manager.dialogue_initiator == human

    def test_exit_dialogue_mode(self):
        """Test exiting dialogue mode."""
        manager = FloorManager()
        human = ParticipantFactory.create_human("User", Role.MEMBER)
        
        manager.enter_dialogue_mode(human)
        manager.exit_dialogue_mode()
        
        assert manager.in_dialogue_mode is False
        assert manager.dialogue_initiator is None

    def test_dialogue_mode_with_floor_control(self):
        """Test dialogue mode integration with floor control."""
        manager = FloorManager()
        human = ParticipantFactory.create_human("User", Role.MEMBER)
        ai = ParticipantFactory.create_ai("Agent", Role.HOST)
        
        # Start dialogue mode
        manager.enter_dialogue_mode(human)
        assert manager.in_dialogue_mode is True
        
        # Human should still be able to speak
        assert manager.can_speak(human) is True
        
        # Exit dialogue mode
        manager.exit_dialogue_mode()
        assert manager.in_dialogue_mode is False
