package handlers

import (
	"encoding/json"
	"net/http"

	"github.com/rede5/gohorsejobs/backend/internal/api/middleware"
	"github.com/rede5/gohorsejobs/backend/internal/services"
)

type ChatHandlers struct {
	chatService *services.ChatService
}

func NewChatHandlers(s *services.ChatService) *ChatHandlers {
	return &ChatHandlers{chatService: s}
}

// ListConversations lists all conversations for the authenticated user
// @Summary List Conversations
// @Description List chat conversations for candidate or company
// @Tags Chat
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {array} services.Conversation
// @Router /api/v1/conversations [get]
func (h *ChatHandlers) ListConversations(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	userID, _ := ctx.Value(middleware.ContextUserID).(string)
	tenantID, _ := ctx.Value(middleware.ContextTenantID).(string)
	roles := middleware.ExtractRoles(ctx.Value(middleware.ContextRoles))

	if userID == "" {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	isCandidate := false
	for _, r := range roles {
		if r == "candidate" || r == "CANDIDATE" {
			isCandidate = true
			break
		}
	}

	// Logic: If user has company (tenantID), prefer company view?
	// But a user might be both candidate and admin (unlikely in this domain model).
	// If tenantID is present, assume acting as Company.
	if tenantID != "" {
		isCandidate = false
	} else {
		isCandidate = true
	}

	convs, err := h.chatService.ListConversations(ctx, userID, tenantID, isCandidate)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(convs)
}

// ListMessages lists messages in a conversation
// @Summary List Messages
// @Description Get message history for a conversation
// @Tags Chat
// @Accept json
// @Produce json
// @Param id path string true "Conversation ID"
// @Security BearerAuth
// @Success 200 {array} services.Message
// @Router /api/v1/conversations/{id}/messages [get]
func (h *ChatHandlers) ListMessages(w http.ResponseWriter, r *http.Request) {
	conversationID := r.PathValue("id")
	if conversationID == "" {
		http.Error(w, "Conversation ID required", http.StatusBadRequest)
		return
	}

	msgs, err := h.chatService.ListMessages(r.Context(), conversationID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Mark "IsMine"
	userID, _ := r.Context().Value(middleware.ContextUserID).(string)
	for i := range msgs {
		if msgs[i].SenderID == userID {
			msgs[i].IsMine = true
		}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(msgs)
}

// SendMessage sends a new message
// @Summary Send Message
// @Description Send a message to a conversation
// @Tags Chat
// @Accept json
// @Produce json
// @Param id path string true "Conversation ID"
// @Param request body map[string]string true "Message Content"
// @Security BearerAuth
// @Success 200 {object} services.Message
// @Router /api/v1/conversations/{id}/messages [post]
func (h *ChatHandlers) SendMessage(w http.ResponseWriter, r *http.Request) {
	conversationID := r.PathValue("id")
	if conversationID == "" {
		http.Error(w, "Conversation ID required", http.StatusBadRequest)
		return
	}

	userID, _ := r.Context().Value(middleware.ContextUserID).(string)
	if userID == "" {
		http.Error(w, "Unauthorized", http.StatusUnauthorized)
		return
	}

	var req struct {
		Content string `json:"content"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid body", http.StatusBadRequest)
		return
	}
	if req.Content == "" {
		http.Error(w, "Content required", http.StatusBadRequest)
		return
	}

	msg, err := h.chatService.SendMessage(r.Context(), userID, conversationID, req.Content)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	msg.IsMine = true
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(msg)
}
