import queue
import logging

logger = logging.getLogger(__name__)

# 存储所有活动的 SSE 连接队列（按商户ID组织）
_connections = {}  # {merchant_id: set([conn_queue1, conn_queue2, ...])}


def get_all_connections_count():
    """获取所有商户的连接总数"""
    total = 0
    for merchant_id, connections in _connections.items():
        total += len(connections)
    return total


def get_merchant_connections(merchant_id):
    """获取指定商户的所有连接队列"""
    return _connections.get(merchant_id, set())


def get_all_merchant_ids():
    """获取所有有活跃连接的商户ID列表"""
    return list(_connections.keys())


def push_connection(merchant_id, conn_queue):
    """
    将一个新的连接队列添加到指定商户的连接集合中
    
    参数:
    - merchant_id: 商户ID
    - conn_queue: queue.Queue 实例
    """
    if merchant_id not in _connections:
        _connections[merchant_id] = set()
    
    _connections[merchant_id].add(conn_queue)
    total_connections = sum(len(conns) for conns in _connections.values())
    logger.info(f"商户 {merchant_id} 的新 SSE 连接建立，该商户连接数: {len(_connections[merchant_id])}，总连接数: {total_connections}")


def remove_connection(merchant_id, conn_queue):
    """
    从指定商户的连接集合中移除一个连接队列
    
    参数:
    - merchant_id: 商户ID
    - conn_queue: queue.Queue 实例
    """
    if merchant_id in _connections:
        _connections[merchant_id].discard(conn_queue)
        
        # 如果该商户没有其他连接，则移除整个商户记录
        if not _connections[merchant_id]:
            del _connections[merchant_id]
        
        total_connections = sum(len(conns) for conns in _connections.values())
        logger.info(f"商户 {merchant_id} 的 SSE 连接断开，该商户连接数: {len(_connections.get(merchant_id, set()))}，总连接数: {total_connections}")
    else:
        logger.warning(f"尝试从未注册的商户 {merchant_id} 移除连接")


def cleanup_all_connections():
    """
    清理所有连接（用于服务器关闭时）
    """
    all_connections = {}
    for merchant_id, connections in list(_connections.items()):
        all_connections[merchant_id] = list(connections)
        for conn_queue in connections:
            try:
                # 发送关闭信号到队列
                if hasattr(conn_queue, 'put_nowait'):
                    conn_queue.put_nowait({'type': 'server_shutdown', 'message': 'Server shutting down'})
                    logger.debug(f'shutdown connection {conn_queue} for merchant {merchant_id}')
            except Exception:
                pass  # 忽略错误，因为连接可能已经断开
    
    _connections.clear()
    logger.info("所有SSE连接已清理")


def shutdown_merchant_connections(merchant_id):
    """
    关闭指定商户的所有连接
    
    参数:
    - merchant_id: 商户ID
    
    返回:
    - int: 关闭的连接数
    """
    if merchant_id not in _connections:
        return 0
    
    connections = _connections[merchant_id]
    count = len(connections)
    
    # 向每个连接发送关闭信号
    for conn_queue in list(connections):
        try:
            conn_queue.put_nowait({
                'type': 'server_shutdown',
                'message': 'Server shutting down your connections, please reconnect later'
            })
        except queue.Full:
            # 队列满了，跳过
            pass
        except Exception:
            # 其他异常，也跳过
            pass
    
    # 删除所有连接
    del _connections[merchant_id]
    
    logger.info(f"关闭商户 {merchant_id} 的 {count} 个 SSE 连接")
    return count


def push_sse_event_to_all(event_data: dict):
    """
    向所有连接的客户端广播一个 SSE 事件（同步队列版本）
    
    参数:
    - event_data: 要发送的事件数据（字典）
    """
    disconnected = {}
    
    for merchant_id, connections in list(_connections.items()):
        disconnected[merchant_id] = []
        
        for conn_queue in connections:
            try:
                # 使用put_nowait非阻塞发送消息
                conn_queue.put_nowait(event_data)
            except queue.Full:
                # 队列满了，说明客户端处理消息太慢，跳过这条消息
                logger.warning(f"商户 {merchant_id} 队列已满，跳过消息: {event_data.get('type', 'unknown')}")
            except Exception as e:
                # 其他异常可能表示连接已断开
                logger.error(f"向商户 {merchant_id} 的队列发送消息失败: {e}")
                disconnected[merchant_id].append(conn_queue)
    
    # 清理断开的连接
    for merchant_id, conn_queues in disconnected.items():
        for conn_queue in conn_queues:
            remove_connection(merchant_id, conn_queue)


def push_sse_event_to_merchant(merchant_id, event_data: dict):
    """
    向指定商户的所有连接客户端广播一个 SSE 事件（同步队列版本）
    
    参数:
    - merchant_id: 目标商户ID
    - event_data: 要发送的事件数据（字典）
    """
    if merchant_id not in _connections:
        logger.info(f"商户 {merchant_id} 没有活跃连接，跳过消息发送")
        return
    
    disconnected = []
    
    for conn_queue in list(_connections[merchant_id]):
        try:
            # 使用put_nowait非阻塞发送消息
            conn_queue.put_nowait(event_data)
        except queue.Full:
            # 队列满了，说明客户端处理消息太慢，跳过这条消息
            logger.warning(f"商户 {merchant_id} 队列已满，跳过消息: {event_data.get('type', 'unknown')}")
        except Exception as e:
            # 其他异常可能表示连接已断开
            logger.error(f"向商户 {merchant_id} 的队列发送消息失败: {e}")
            disconnected.append(conn_queue)
    
    # 清理断开的连接
    for conn_queue in disconnected:
        remove_connection(merchant_id, conn_queue)
    
    logger.info(f"向商户 {merchant_id} 广播 SSE 事件: type={event_data.get('type', 'unknown')}, 接收客户端数={len(_connections.get(merchant_id, set()))}")


def push_simple_message_with_object_id(event_type: str, message: str, object_id):
    """
    向所有连接的客户端广播一个简单消息事件，包含关联对象ID（WSGI同步版本）
    
    参数:
    - event_type: 事件类型字符串
    - message: 消息内容字符串
    - object_id: 关联对象的ID（整数或字符串）
    """
    event_data = {
        'mode': 'simple_message',
        'type': event_type,
        'message': message,
        'object_id': object_id,
    }
    push_sse_event_to_all(event_data)
    total_connections = sum(len(conns) for conns in _connections.values())
    logger.info(f"广播 SSE 事件: type={event_type}, object_id={object_id}, 接收客户端数={total_connections}")


def push_simple_message_with_object_id_to_merchant(merchant_id, event_type: str, message: str, object_id):
    """
    向指定商户的所有连接客户端广播一个简单消息事件，包含关联对象ID
    
    参数:
    - merchant_id: 目标商户ID
    - event_type: 事件类型字符串
    - message: 消息内容字符串
    - object_id: 关联对象的ID（整数或字符串）
    """
    event_data = {
        'mode': 'simple_message',
        'type': event_type,
        'message': message,
        'object_id': object_id,
        'merchant_id': merchant_id,  # 添加商户ID，便于客户端验证
    }
    push_sse_event_to_merchant(merchant_id, event_data)
