import socketio
import base64
import io
import threading

class ConvaiChatClient:
    """
    Python plugin for interacting with  Flask-SocketIO chat backend.
    """

    def __init__(self, server_url="http://localhost:5000", reconnect=True):
        self.sio = socketio.Client(reconnection=reconnect)
        self.server_url = server_url
        self._register_default_handlers()
        self._background_thread = None
        self._lock = threading.Lock()

    def _register_default_handlers(self):
        @self.sio.event
        def connect():
            print(f"✅ Connected to {self.server_url}")

        @self.sio.event
        def disconnect():
            print("❌ Disconnected from server")

        @self.sio.on('message')
        def on_message(data):
            print(f"📨 Message: {data}")

        @self.sio.on('chat_response')
        def on_chat_response(data):
            print(f"💬 Chat response: {data['text']}")

        @self.sio.on('update_success')
        def on_update_success(data):
            print(f"✅ Update success: {data['message']}")

    def connect(self):
        """Establish socket connection."""
        self.sio.connect(self.server_url)

    def disconnect(self):
        """Disconnect the socket."""
        self.sio.disconnect()

    def send_text(self, message, character_id=None, section_id=None):
        """
        Emit a text_chat event.
        """
        payload = {"userInput": message}
        if character_id is not None:
            payload["character_id"] = character_id
        if section_id is not None:
            payload["section_id"] = section_id
        self.sio.emit("text_chat", payload)

    def update_character(self, character_id):
        """
        Emit update_Character_id event to set current character.
        """
        self.sio.emit("update_Character_id", {"character_id": character_id})

    def start_audio(self):
        """Begin streaming audio."""
        self.sio.emit("start_audio_stream")

    def send_audio_chunk(self, chunk_bytes):
        """
        Send a chunk of raw audio bytes.
        Convert bytes to base64 string automatically.
        """
        b64 = base64.b64encode(chunk_bytes).decode('utf-8')
        self.sio.emit("audio_chunk", b64)

    def end_audio(self):
        """End audio streaming and trigger processing."""
        self.sio.emit("end_audio_stream")

    def toggle_action_mode(self, enabled=True):
        """Enable or disable action mode."""
        self.sio.emit("toggle_action_mode", {"enabled": enabled})

    def on(self, event, handler):
        """
        Register a custom event handler.
        e.g., plugin.on('chat_response', lambda data: print(data))
        """
        self.sio.on(event, handler)

    def wait(self):
        """Block thread to keep listening."""
        self.sio.wait()

