package hub

import (
	"sync"

	"github.com/gorilla/websocket"
)

// Connection 包装单个 WebSocket 连接及其异步发送通道
type Connection struct {
	UserID string
	conn   *websocket.Conn
	send   chan []byte
}

// Send 将消息投递到该连接的发送通道（非阻塞，通道满则丢弃）
func (c *Connection) Send(message []byte) {
	select {
	case c.send <- message:
	default:
		// 通道满，丢弃消息避免阻塞 hub
	}
}

// Outgoing 返回该连接的发送通道，供写协程消费
func (c *Connection) Outgoing() <-chan []byte {
	return c.send
}

// Hub 管理所有在线 WebSocket 连接，按 userID 索引
type Hub struct {
	mu      sync.RWMutex
	clients map[string]map[*Connection]bool
}

// NewHub 创建 Hub 实例
func NewHub() *Hub {
	return &Hub{
		clients: make(map[string]map[*Connection]bool),
	}
}

// ClientCount 返回当前在线连接总数（供 /readyz 探针使用）
func (h *Hub) ClientCount() int {
	h.mu.RLock()
	defer h.mu.RUnlock()
	count := 0
	for _, conns := range h.clients {
		count += len(conns)
	}
	return count
}

// Register 注册一个用户连接，返回 Connection 供调用方持有
func (h *Hub) Register(userID string, conn *websocket.Conn) *Connection {
	c := &Connection{
		UserID: userID,
		conn:   conn,
		send:   make(chan []byte, 64),
	}
	h.mu.Lock()
	defer h.mu.Unlock()
	if h.clients[userID] == nil {
		h.clients[userID] = make(map[*Connection]bool)
	}
	h.clients[userID][c] = true
	return c
}

// Unregister 注销一个用户连接并关闭其发送通道
func (h *Hub) Unregister(c *Connection) {
	h.mu.Lock()
	defer h.mu.Unlock()
	conns, ok := h.clients[c.UserID]
	if !ok {
		return
	}
	if _, exists := conns[c]; exists {
		delete(conns, c)
		close(c.send)
	}
	if len(conns) == 0 {
		delete(h.clients, c.UserID)
	}
}

// SendToUser 向指定用户的所有在线连接推送消息
func (h *Hub) SendToUser(userID string, message []byte) error {
	h.mu.RLock()
	defer h.mu.RUnlock()
	conns, ok := h.clients[userID]
	if !ok {
		return nil
	}
	for c := range conns {
		c.Send(message)
	}
	return nil
}

// Broadcast 向所有在线连接广播消息
func (h *Hub) Broadcast(message []byte) {
	h.mu.RLock()
	defer h.mu.RUnlock()
	for _, conns := range h.clients {
		for c := range conns {
			c.Send(message)
		}
	}
}
