"""
IPC Server Entry Point
Provides a unified interface for Electron-Python communication
- Windows: Uses Named Pipes
- Linux/macOS: Uses TCP sockets

This module automatically selects the appropriate transport based on the platform.
"""

import sys
import platform
from typing import Optional

from ws_package.log.writer import LogWriter

logger = LogWriter.file(__name__)

# Platform detection
IS_WINDOWS = platform.system() == 'Windows'

# Lazy import to avoid loading unnecessary modules
_ipc_server_instance = None


def get_ipc_server():
    """
    Get the global IPC server instance (singleton).
    Automatically selects Named Pipes on Windows, TCP on Linux/macOS.
    """
    global _ipc_server_instance
    
    if _ipc_server_instance is None:
        if IS_WINDOWS:
            # Windows: Use Named Pipes
            from ws_package.utils.pipe_server import get_pipe_server
            _ipc_server_instance = get_pipe_server()
            logger.info("IPC server: Using Named Pipes (Windows)")
        else:
            # Linux/macOS: Use TCP
            from ws_package.utils.tcp_server import get_tcp_server
            _ipc_server_instance = get_tcp_server()
            logger.info("IPC server: Using TCP (Linux/macOS)")
    
    return _ipc_server_instance


def start_ipc_server():
    """
    Start the IPC server (call this at startup).
    Automatically selects the appropriate transport based on platform.
    """
    server = get_ipc_server()
    if hasattr(server, 'start'):
        server.start()
    else:
        logger.error("IPC server does not have start() method")
        raise AttributeError("IPC server does not have start() method")


def stop_ipc_server():
    """
    Stop the IPC server (call this at shutdown).
    """
    global _ipc_server_instance
    
    if _ipc_server_instance:
        if hasattr(_ipc_server_instance, 'stop'):
            _ipc_server_instance.stop()
        _ipc_server_instance = None
        logger.info("IPC server stopped")


def is_ipc_ready() -> bool:
    """
    Check if IPC server is ready and running.
    For Named Pipes on Windows, also checks that the pipe is actually created.
    """
    if _ipc_server_instance is None:
        return False
    
    # Check if server is running
    if hasattr(_ipc_server_instance, 'running'):
        if not _ipc_server_instance.running:
            return False
    elif hasattr(_ipc_server_instance, 'is_running'):
        if not _ipc_server_instance.is_running():
            return False
    else:
        return False
    
    # For Named Pipes, also check that the pipe is actually created
    if IS_WINDOWS and hasattr(_ipc_server_instance, 'pipe_created'):
        # Wait up to 2 seconds for pipe to be created (non-blocking check)
        if not _ipc_server_instance.pipe_created.wait(timeout=0.1):
            # Pipe not created yet, but server is running - return True anyway
            # The pipe will be created soon in the accept thread
            return True
        return True
    
    return True


def is_connected() -> bool:
    """
    Check if Electron client is connected.
    """
    if _ipc_server_instance is None:
        return False
    
    if hasattr(_ipc_server_instance, 'is_connected'):
        return _ipc_server_instance.is_connected()
    
    return False


def send_message(message_type: str, data: Optional[dict] = None) -> bool:
    """
    Send message to Electron client.
    
    Args:
        message_type: Type of message (e.g., 'idle_popup_trigger', 'activity_update')
        data: Optional data dictionary to send
        
    Returns:
        True if sent successfully, False otherwise
    """
    if _ipc_server_instance is None:
        return False
    
    if hasattr(_ipc_server_instance, 'send_message'):
        return _ipc_server_instance.send_message(message_type, data)
    
    return False


def get_message(timeout: Optional[float] = None) -> Optional[dict]:
    """
    Get a message from Electron client (non-blocking or with timeout).
    
    Args:
        timeout: Timeout in seconds. If None, perform non-blocking check.
                 If 0, block indefinitely. Otherwise, block up to `timeout` seconds.
        
    Returns:
        Message dictionary or None if no message available / timeout.
    """
    if _ipc_server_instance is None:
        return None
    
    if hasattr(_ipc_server_instance, 'get_message'):
        return _ipc_server_instance.get_message(timeout=timeout)
    
    return None

