//go:build ignore
// +build ignore

// TODO: Réactiver chat_handlers après stabilisation du noyau et alignement des services (ChatService, MessageType, RoomType)

package handlers

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"

	"veza-backend-api/internal/services"
)

// ChatHandlers handles chat-related API endpoints
type ChatHandlers struct {
	chatService *services.ChatService
	logger      *zap.Logger
}

// NewChatHandlers creates new chat handlers
func NewChatHandlers(chatService *services.ChatService, logger *zap.Logger) *ChatHandlers {
	return &ChatHandlers{
		chatService: chatService,
		logger:      logger,
	}
}

// InitChatHandlers initializes chat handlers
func InitChatHandlers(chatService *services.ChatService, logger *zap.Logger) {
	handlers := NewChatHandlers(chatService, logger)

	// Store handlers globally for route registration
	ChatHandlersInstance = handlers
}

// ChatHandlersInstance holds the global chat handlers instance
var ChatHandlersInstance *ChatHandlers

// CreateMessage creates a new message in a room
func (h *ChatHandlers) CreateMessage(c *gin.Context) {
	userID := c.GetInt64("user_id")
	roomID, err := strconv.ParseInt(c.Param("room_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
		return
	}

	var req struct {
		Content  string               `json:"content" binding:"required"`
		Type     services.MessageType `json:"type"`
		ParentID *int64               `json:"parent_id,omitempty"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if req.Type == "" {
		req.Type = services.MessageTypeText
	}

	message, err := h.chatService.CreateMessage(c.Request.Context(), roomID, userID, req.Content, req.Type, req.ParentID)
	if err != nil {
		h.logger.Error("Failed to create message", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create message"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"success": true,
		"message": message,
	})
}

// GetMessages retrieves messages for a room
func (h *ChatHandlers) GetMessages(c *gin.Context) {
	roomID, err := strconv.ParseInt(c.Param("room_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50"))
	beforeIDStr := c.Query("before_id")

	var beforeID *int64
	if beforeIDStr != "" {
		if id, err := strconv.ParseInt(beforeIDStr, 10, 64); err == nil {
			beforeID = &id
		}
	}

	messages, err := h.chatService.GetMessages(c.Request.Context(), roomID, page, limit, beforeID)
	if err != nil {
		h.logger.Error("Failed to get messages", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get messages"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":  true,
		"messages": messages,
		"page":     page,
		"limit":    limit,
	})
}

// AddReaction adds a reaction to a message
func (h *ChatHandlers) AddReaction(c *gin.Context) {
	userID := c.GetInt64("user_id")
	messageID, err := strconv.ParseInt(c.Param("message_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid message ID"})
		return
	}

	var req struct {
		Emoji string `json:"emoji" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	reaction, err := h.chatService.AddReaction(c.Request.Context(), messageID, userID, req.Emoji)
	if err != nil {
		h.logger.Error("Failed to add reaction", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to add reaction"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"success":  true,
		"reaction": reaction,
	})
}

// RemoveReaction removes a reaction from a message
func (h *ChatHandlers) RemoveReaction(c *gin.Context) {
	userID := c.GetInt64("user_id")
	messageID, err := strconv.ParseInt(c.Param("message_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid message ID"})
		return
	}

	emoji := c.Param("emoji")
	if emoji == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Emoji is required"})
		return
	}

	err = h.chatService.RemoveReaction(c.Request.Context(), messageID, userID, emoji)
	if err != nil {
		h.logger.Error("Failed to remove reaction", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to remove reaction"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "Reaction removed",
	})
}

// CreateRoom creates a new chat room
func (h *ChatHandlers) CreateRoom(c *gin.Context) {
	userID := c.GetInt64("user_id")

	var req struct {
		Name        string            `json:"name" binding:"required"`
		Description string            `json:"description"`
		Type        services.RoomType `json:"type"`
		IsPrivate   bool              `json:"is_private"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if req.Type == "" {
		req.Type = services.RoomTypePublic
	}

	room, err := h.chatService.CreateRoom(c.Request.Context(), req.Name, req.Description, req.Type, req.IsPrivate, userID)
	if err != nil {
		h.logger.Error("Failed to create room", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create room"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"success": true,
		"room":    room,
	})
}

// GetRooms retrieves available rooms
func (h *ChatHandlers) GetRooms(c *gin.Context) {
	userID := c.GetInt64("user_id")
	includePrivate := c.DefaultQuery("include_private", "false") == "true"

	rooms, err := h.chatService.GetRooms(c.Request.Context(), userID, includePrivate)
	if err != nil {
		h.logger.Error("Failed to get rooms", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get rooms"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"rooms":   rooms,
	})
}

// JoinRoom adds a user to a room
func (h *ChatHandlers) JoinRoom(c *gin.Context) {
	userID := c.GetInt64("user_id")
	roomID, err := strconv.ParseInt(c.Param("room_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
		return
	}

	err = h.chatService.JoinRoom(c.Request.Context(), roomID, userID)
	if err != nil {
		h.logger.Error("Failed to join room", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to join room"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "Successfully joined room",
	})
}

// LeaveRoom removes a user from a room
func (h *ChatHandlers) LeaveRoom(c *gin.Context) {
	userID := c.GetInt64("user_id")
	roomID, err := strconv.ParseInt(c.Param("room_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
		return
	}

	err = h.chatService.LeaveRoom(c.Request.Context(), roomID, userID)
	if err != nil {
		h.logger.Error("Failed to leave room", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to leave room"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "Successfully left room",
	})
}

// CreateDirectMessage creates a DM room between two users
func (h *ChatHandlers) CreateDirectMessage(c *gin.Context) {
	userID := c.GetInt64("user_id")

	var req struct {
		UserID int64 `json:"user_id" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	room, err := h.chatService.CreateDirectMessage(c.Request.Context(), userID, req.UserID)
	if err != nil {
		h.logger.Error("Failed to create DM", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create direct message"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"success": true,
		"room":    room,
	})
}

// SearchMessages searches for messages in a room
func (h *ChatHandlers) SearchMessages(c *gin.Context) {
	roomID, err := strconv.ParseInt(c.Param("room_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
		return
	}

	query := c.Query("q")
	if query == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Search query is required"})
		return
	}

	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))

	messages, err := h.chatService.SearchMessages(c.Request.Context(), roomID, query, limit)
	if err != nil {
		h.logger.Error("Failed to search messages", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to search messages"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":  true,
		"messages": messages,
		"query":    query,
		"limit":    limit,
	})
}

// EditMessage edits an existing message
func (h *ChatHandlers) EditMessage(c *gin.Context) {
	userID := c.GetInt64("user_id")
	messageID, err := strconv.ParseInt(c.Param("message_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid message ID"})
		return
	}

	var req struct {
		Content string `json:"content" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	message, err := h.chatService.EditMessage(c.Request.Context(), messageID, userID, req.Content)
	if err != nil {
		h.logger.Error("Failed to edit message", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to edit message"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": message,
	})
}

// DeleteMessage deletes a message
func (h *ChatHandlers) DeleteMessage(c *gin.Context) {
	userID := c.GetInt64("user_id")
	messageID, err := strconv.ParseInt(c.Param("message_id"), 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid message ID"})
		return
	}

	err = h.chatService.DeleteMessage(c.Request.Context(), messageID, userID)
	if err != nil {
		h.logger.Error("Failed to delete message", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete message"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "Message deleted successfully",
	})
}
