package handlers

import (
	"net/http"
	"time"

	"github.com/google/uuid"

	"{{GO_MODULE}}/pkg/app"
	"{{GO_MODULE}}/pkg/auth"
	"{{GO_MODULE}}/pkg/httpresponse"
	"{{GO_MODULE}}/pkg/logging"
	"{{GO_MODULE}}/pkg/queue"
	"{{GO_MODULE}}/pkg/realtime"
)

// Chat handles HTTP requests for chat messaging with AI responses.
// User messages are broadcast immediately via SSE.
// AI responses are enqueued and processed by the worker with streaming chunks.
type Chat struct {
	queue  queue.Producer
	sseHub *realtime.SSEHub
	logger *logging.Logger
}

// NewChat creates a new Chat handler.
func NewChat(q queue.Producer, hub *realtime.SSEHub, logger *logging.Logger) *Chat {
	return &Chat{
		queue:  q,
		sseHub: hub,
		logger: logger.WithComponent("ChatHandler"),
	}
}

// SendMessageRequest is the request body for sending a chat message.
type SendMessageRequest struct {
	Content string `json:"content" validate:"required,min=1,max=5000"`
}

// SendMessage broadcasts a chat message to a channel via SSE
// and enqueues an AI response job for the worker.
func (h *Chat) SendMessage(w http.ResponseWriter, r *http.Request) error {
	var req SendMessageRequest
	if err := app.BindAndValidate(r, &req); err != nil {
		return err
	}

	// Get user info
	userID := "anonymous"
	userName := "Anonymous"
	if user := auth.GetUser(r.Context()); user != nil {
		userID = user.ID
		if name, ok := user.Metadata["name"].(string); ok && name != "" {
			userName = name
		} else if user.Email != "" {
			userName = user.Email
		}
	}

	msgID := uuid.New().String()
	now := time.Now().UTC()

	// Broadcast user message to channel:general immediately (synchronous — users
	// see their own messages instantly without waiting for the queue)
	h.sseHub.SendToChannel("channel:general", &realtime.SSEEvent{
		Type:      "chat",
		Timestamp: now,
		JobID:     msgID,
		Message:   req.Content,
		Result: map[string]any{
			"id":        msgID,
			"content":   req.Content,
			"userId":    userID,
			"userName":  userName,
			"timestamp": now.Format(time.RFC3339),
		},
	})

	// Enqueue AI response job — worker streams chunks via Redis → SSE
	if _, err := h.queue.Enqueue(r.Context(), "ai_chat_response", map[string]any{
		"content": req.Content,
		"userID":  userID,
		"channel": "channel:general",
	}); err != nil {
		h.logger.Error("failed to enqueue AI chat response", "error", err)
		// Don't fail the request — user message was already delivered
	}

	httpresponse.OK(w, r, map[string]string{
		"id":     msgID,
		"status": "sent",
	})
	return nil
}
