package internal import ( "fmt" "sync" "github.com/gorilla/websocket" ) // Client represents a connected user WebSocket connection. type Client struct { UID string Conn *websocket.Conn } // Hub manages connected clients and their WebSocket connections. type Hub struct { mu sync.RWMutex clients map[string]*Client // uid -> client } // NewHub creates a new Hub. func NewHub() *Hub { return &Hub{clients: make(map[string]*Client)} } // Register adds a client connection. func (h *Hub) Register(uid string, conn *websocket.Conn) { h.mu.Lock() defer h.mu.Unlock() // Close existing connection if any if old, ok := h.clients[uid]; ok { old.Conn.Close() } h.clients[uid] = &Client{UID: uid, Conn: conn} } // Unregister removes a client connection. func (h *Hub) Unregister(uid string) { h.mu.Lock() defer h.mu.Unlock() delete(h.clients, uid) } // GetClient returns a client by uid. func (h *Hub) GetClient(uid string) *Client { h.mu.RLock() defer h.mu.RUnlock() return h.clients[uid] } // PushToClient sends a JSON message to a specific client. // Returns an error if the client is not connected. func (h *Hub) PushToClient(uid string, msg []byte) error { client := h.GetClient(uid) if client == nil { return fmt.Errorf("client %s not connected", uid) } return client.Conn.WriteMessage(websocket.TextMessage, msg) }