"""
Mock output handlers for testing.

This module provides mock output implementations that collect game output
instead of sending it over WebSocket, allowing tests to inspect what would
have been sent to the client.
"""
from typing import List, Dict, Any, Optional
from datetime import datetime

class CollectorOutput:
    """Collects all game output instead of sending to WebSocket"""

    def __init__(self):
        self.events: List[Any] = []
        self.messages: List[str] = []
        self.questions: List[Any] = []
        self.player_updates: List[Any] = []
        self.dict_messages: List[Dict] = []

    async def send_event_message(self, event_obj):
        """Collect event message (matches IGameOutput interface)"""
        if hasattr(event_obj, 'type'):
            if event_obj.type == 'questionEvent':
                self.questions.append(event_obj)
            else:
                self.events.append(event_obj)
        else:
            self.events.append(event_obj)

    async def send_user_info(self, player):
        """Collect player update (matches IGameOutput interface)"""
        self.player_updates.append(player)

    async def send_dict(self, obj):
        """Collect dictionary message (matches IGameOutput interface)"""
        self.dict_messages.append(obj)

    # Legacy methods for backwards compatibility
    async def send_event(self, event):
        """Legacy send event method"""
        await self.send_event_message(event)

    async def send_message(self, message):
        """Collect message instead of sending"""
        self.messages.append(message)

    async def send_question(self, question):
        """Legacy send question method"""
        self.questions.append(question)

    async def send_player_update(self, player_data):
        """Legacy send player update method"""
        self.player_updates.append(player_data)

    def get_latest_event(self):
        """Get most recent event"""
        return self.events[-1] if self.events else None

    def get_events_by_type(self, event_type):
        """Filter events by type"""
        return [e for e in self.events if hasattr(e, 'type') and e.type == event_type]

    def clear(self):
        """Reset all collections"""
        self.events.clear()
        self.messages.clear()
        self.questions.clear()
        self.player_updates.clear()
        self.dict_messages.clear()


# Alias for backwards compatibility with output.py
class MockGameOutput(CollectorOutput):
    """Alias for CollectorOutput"""
    pass


class MockOutput(CollectorOutput):
    """
    Mock output with additional testing features.

    Extends CollectorOutput with methods for simulating failures
    and controlling output behavior.
    """

    def __init__(self):
        """Initialize mock output."""
        super().__init__()
        self._should_fail = False
        self._fail_on_type = None
        self.call_count = 0

    async def send_event_message(self, event_obj):
        """Send event message with failure simulation."""
        self.call_count += 1
        if self._should_fail or self._fail_on_type == 'event':
            raise Exception("Simulated event send failure")
        await super().send_event_message(event_obj)

    async def send_user_info(self, player):
        """Send user info with failure simulation."""
        self.call_count += 1
        if self._should_fail or self._fail_on_type == 'user_info':
            raise Exception("Simulated user info send failure")
        await super().send_user_info(player)

    async def send_dict(self, obj):
        """Send dict with failure simulation."""
        self.call_count += 1
        if self._should_fail or self._fail_on_type == 'dict':
            raise Exception("Simulated dict send failure")
        await super().send_dict(obj)

    def simulate_failure(self):
        """Configure output to fail on all sends."""
        self._should_fail = True

    def simulate_failure_on_type(self, output_type: str):
        """
        Configure output to fail on specific type.

        Args:
            output_type: Type to fail on ('event', 'user_info', 'dict')
        """
        self._fail_on_type = output_type

    def reset_failures(self):
        """Reset failure simulation."""
        self._should_fail = False
        self._fail_on_type = None

    def get_stats(self) -> Dict[str, int]:
        """
        Get statistics about collected output.

        Returns:
            Dict: Statistics dictionary
        """
        return {
            'events': len(self.events),
            'messages': len(self.messages),
            'questions': len(self.questions),
            'player_updates': len(self.player_updates),
            'dict_messages': len(self.dict_messages),
            'call_count': self.call_count
        }

    def __repr__(self):
        return f"MockOutput(events={len(self.events)}, questions={len(self.questions)}, calls={self.call_count})"
