package websocket

import (
	"encoding/json"
	"log"
	"sync"

	"github.com/gorilla/websocket"
)

type client struct {
	conn *websocket.Conn
	send chan []byte
	mu   sync.Mutex
}

type Hub struct {
	mu      sync.RWMutex
	clients map[*websocket.Conn]*client
}

func NewHub() *Hub {
	return &Hub{clients: make(map[*websocket.Conn]*client)}
}

func (h *Hub) Register(conn *websocket.Conn) {
	c := &client{conn: conn, send: make(chan []byte, 64)}
	h.mu.Lock()
	h.clients[conn] = c
	h.mu.Unlock()
	go c.writePump()
}

func (h *Hub) Unregister(conn *websocket.Conn) {
	h.mu.Lock()
	if c, ok := h.clients[conn]; ok {
		close(c.send)
		delete(h.clients, conn)
	}
	h.mu.Unlock()
}

func (h *Hub) Broadcast(msg interface{}) {
	data, err := json.Marshal(msg)
	if err != nil {
		log.Printf("[ws] marshal: %v", err)
		return
	}
	h.mu.RLock()
	defer h.mu.RUnlock()
	for _, c := range h.clients {
		select {
		case c.send <- data:
		default:
			// canal plein, client lent — on skip
		}
	}
}

func (h *Hub) Count() int {
	h.mu.RLock()
	defer h.mu.RUnlock()
	return len(h.clients)
}

func (c *client) writePump() {
	defer c.conn.Close()
	for data := range c.send {
		if err := c.conn.WriteMessage(websocket.TextMessage, data); err != nil {
			log.Printf("[ws] write: %v", err)
			return
		}
	}
}
