package handlers

import (
	"net/http"
	"strconv"
	
	"veza-backend-api/internal/services"
	
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"
)

// RoomHandler gère les opérations sur les rooms (conversations)
type RoomHandler struct {
	roomService *services.RoomService
	logger      *zap.Logger
}

// NewRoomHandler crée une nouvelle instance de RoomHandler
func NewRoomHandler(roomService *services.RoomService, logger *zap.Logger) *RoomHandler {
	return &RoomHandler{
		roomService: roomService,
		logger:      logger,
	}
}

// CreateRoom gère la création d'une nouvelle room
// POST /api/v1/conversations
func (h *RoomHandler) CreateRoom(c *gin.Context) {
	// Récupérer l'ID utilisateur du contexte
	userIDInterface, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}
	
	// Convertir userID en int64
	var userID int64
	switch v := userIDInterface.(type) {
	case int:
		userID = int64(v)
	case int64:
		userID = v
	case string:
		id, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
			return
		}
		userID = id
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID type"})
		return
	}
	
	// Parser la requête
	var req services.CreateRoomRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		h.logger.Warn("invalid create room request",
			zap.Error(err),
			zap.Int64("user_id", userID))
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	
	// Valider le type de room si non spécifié
	if req.Type == "" {
		req.Type = "public"
	}
	
	
	
	// Créer la room
	
	room, err := h.roomService.CreateRoom(c.Request.Context(), userID, req)
	
	if err != nil {
	
		h.logger.Error("failed to create room",
	
			zap.Error(err),
	
			zap.Int64("user_id", userID),
	
			zap.String("room_name", req.Name))
	
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create conversation"})
	
		return
	
	}
	
	
	
h.logger.Info("room created successfully",
	
		zap.String("room_id", room.ID.String()), // Use String() for UUID
	
		zap.Int64("user_id", userID),
	
		zap.String("room_name", req.Name))
	
	
	
c.JSON(http.StatusCreated, room)
	
}
// GetUserRooms récupère toutes les rooms d'un utilisateur
// GET /api/v1/conversations
func (h *RoomHandler) GetUserRooms(c *gin.Context) {
	// Récupérer l'ID utilisateur du contexte
	userIDInterface, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}
	
	// Convertir userID en int64
	var userID int64
	switch v := userIDInterface.(type) {
	case int:
		userID = int64(v)
	case int64:
		userID = v
	case string:
		id, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
			return
		}
		userID = id
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID type"})
		return
	}
	
	// Récupérer les rooms
	rooms, err := h.roomService.GetUserRooms(c.Request.Context(), userID)
	if err != nil {
		h.logger.Error("failed to get user rooms",
			zap.Error(err),
			zap.Int64("user_id", userID))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch conversations"})
		return
	}
	
	c.JSON(http.StatusOK, gin.H{
		"conversations": rooms,
		"total":         len(rooms),
	})
}

// GetRoom récupère une room par son ID
// GET /api/v1/conversations/:id
func (h *RoomHandler) GetRoom(c *gin.Context) {
	// Récupérer l'ID de la room depuis l'URL
	roomIDStr := c.Param("id")
	roomID, err := uuid.Parse(roomIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
		return
	}
	
	// Récupérer la room
	room, err := h.roomService.GetRoom(c.Request.Context(), roomID)
	if err != nil {
		h.logger.Error("failed to get room",
			zap.Error(err),
			zap.String("room_id", roomID.String()))
		c.JSON(http.StatusNotFound, gin.H{"error": "Conversation not found"})
		return
	}
	
	c.JSON(http.StatusOK, room)
}

// AddMemberRequest représente une requête pour ajouter un membre à une room
type AddMemberRequest struct {
	UserID int64 `json:"user_id" binding:"required"`
}

// AddMember ajoute un membre à une room
// POST /api/v1/conversations/:id/members
func (h *RoomHandler) AddMember(c *gin.Context) {
	// Récupérer l'ID de la room depuis l'URL
	roomIDStr := c.Param("id")
	roomID, err := uuid.Parse(roomIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"})
		return
	}
	
	// Parser la requête
	var req AddMemberRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	
	// Ajouter le membre
	if err := h.roomService.AddMember(c.Request.Context(), roomID, req.UserID); err != nil {
		h.logger.Error("failed to add member to room",
			zap.Error(err),
			zap.String("room_id", roomID.String()),
			zap.Int64("user_id", req.UserID))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to add member"})
		return
	}
	
	h.logger.Info("member added to room",
		zap.String("room_id", roomID.String()),
		zap.Int64("user_id", req.UserID))
	
	c.JSON(http.StatusOK, gin.H{"message": "Member added successfully"})
}

// GetRoomHistory récupère l'historique des messages d'une room
// GET /api/v1/conversations/:id/history
func (h *RoomHandler) GetRoomHistory(c *gin.Context) {
	conversationIDStr := c.Param("id")
	conversationID, err := uuid.Parse(conversationIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid conversation ID"})
		return
	}

	limit := c.DefaultQuery("limit", "50")
	offset := c.DefaultQuery("offset", "0")

	limitInt, err := strconv.Atoi(limit)
	if err != nil || limitInt <= 0 {
		limitInt = 50
	}
	offsetInt, err := strconv.Atoi(offset)
	if err != nil || offsetInt < 0 {
		offsetInt = 0
	}

	messages, err := h.roomService.GetRoomHistory(c.Request.Context(), conversationID, limitInt, offsetInt)
	if err != nil {
		h.logger.Error("failed to get room history",
			zap.Error(err),
			zap.String("conversation_id", conversationID.String()))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get conversation history"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"messages": messages})
}

