package handlers

// presence.go — Heartbeat upsert and status query (v0.23.1)
//
// Clients POST /api/v1/presence/heartbeat every 30s while active.
// GET  /api/v1/presence?users=id1,id2 returns current status.
// Online = last_seen within 90s.
//
// v0.29.0: Raw SQL replaced with PresenceStore + UserStore methods.

import (
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/gin"

	"switchboard-core/store"
)

const presenceOnlineThreshold = 90 * time.Second

type PresenceHandler struct {
	stores store.Stores
}

func NewPresenceHandler(s store.Stores) *PresenceHandler {
	return &PresenceHandler{stores: s}
}

// PresenceHeartbeat upserts the calling user's last_seen timestamp.
func (h *PresenceHandler) Heartbeat(c *gin.Context) {
	userID := getUserID(c)
	if err := h.stores.Presence.Heartbeat(c.Request.Context(), userID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "presence update failed"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

// PresenceQuery returns online/offline status for a list of user IDs.
// Query param: ?users=uuid1,uuid2,...
func (h *PresenceHandler) Query(c *gin.Context) {
	raw := c.Query("users")
	if raw == "" {
		c.JSON(http.StatusOK, gin.H{"presence": map[string]string{}})
		return
	}
	ids := strings.Split(raw, ",")
	if len(ids) > 100 {
		ids = ids[:100]
	}

	// Trim whitespace
	cleaned := make([]string, 0, len(ids))
	for _, id := range ids {
		id = strings.TrimSpace(id)
		if id != "" {
			cleaned = append(cleaned, id)
		}
	}

	threshold := time.Now().Add(-presenceOnlineThreshold)
	result, err := h.stores.Presence.GetStatuses(c.Request.Context(), cleaned, threshold)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "presence query failed"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"presence": result})
}

// SearchUsers returns a lightweight list of approved users matching a query.
// GET /api/v1/users/search?q=alice
func (h *PresenceHandler) SearchUsers(c *gin.Context) {
	userID := getUserID(c)
	q := strings.TrimSpace(c.Query("q"))

	results, err := h.stores.Users.SearchActive(c.Request.Context(), userID, q)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "search failed"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": results})
}
