package handlers import ( "net/http" "strconv" "github.com/gin-gonic/gin" "customer-support-system/internal/conversation" "customer-support-system/internal/models" "customer-support-system/pkg/logger" ) // ConversationHandler handles conversation-related HTTP requests type ConversationHandler struct { conversationService *conversation.ConversationService } // NewConversationHandler creates a new conversation handler func NewConversationHandler() *ConversationHandler { return &ConversationHandler{ conversationService: conversation.NewConversationService(), } } // CreateConversation handles creating a new conversation func (h *ConversationHandler) CreateConversation(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } var req models.CreateConversationRequest if err := c.ShouldBindJSON(&req); err != nil { logger.WithError(err).Error("Failed to parse create conversation request") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid request body", }) return } // Create conversation conv, err := h.conversationService.CreateConversation(userID.(uint), &req) if err != nil { logger.WithError(err).Error("Failed to create conversation") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to create conversation", }) return } c.JSON(http.StatusCreated, gin.H{ "success": true, "message": "Conversation created successfully", "data": gin.H{ "conversation": conv, }, }) } // GetConversation handles getting a conversation by ID func (h *ConversationHandler) GetConversation(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get conversation ID from URL params conversationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse conversation ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid conversation ID", }) return } // Get conversation conv, err := h.conversationService.GetConversation(uint(conversationID), userID.(uint)) if err != nil { logger.WithError(err).Error("Failed to get conversation") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to get conversation", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "data": gin.H{ "conversation": conv, }, }) } // ListConversations handles listing conversations for a user func (h *ConversationHandler) ListConversations(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Parse query parameters page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "10")) status := c.DefaultQuery("status", "") if page < 1 { page = 1 } if pageSize < 1 || pageSize > 100 { pageSize = 10 } // List conversations response, err := h.conversationService.ListConversations(userID.(uint), page, pageSize, status) if err != nil { logger.WithError(err).Error("Failed to list conversations") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to list conversations", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "data": gin.H{ "conversations": response.Conversations, "total": response.Total, "page": response.Page, "pageSize": response.PageSize, }, }) } // UpdateConversation handles updating a conversation func (h *ConversationHandler) UpdateConversation(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get conversation ID from URL params conversationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse conversation ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid conversation ID", }) return } var req models.UpdateConversationRequest if err := c.ShouldBindJSON(&req); err != nil { logger.WithError(err).Error("Failed to parse update conversation request") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid request body", }) return } // Update conversation conv, err := h.conversationService.UpdateConversation(uint(conversationID), userID.(uint), &req) if err != nil { logger.WithError(err).Error("Failed to update conversation") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to update conversation", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Conversation updated successfully", "data": gin.H{ "conversation": conv, }, }) } // DeleteConversation handles deleting a conversation func (h *ConversationHandler) DeleteConversation(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get conversation ID from URL params conversationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse conversation ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid conversation ID", }) return } // Delete conversation err = h.conversationService.DeleteConversation(uint(conversationID), userID.(uint)) if err != nil { logger.WithError(err).Error("Failed to delete conversation") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to delete conversation", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Conversation deleted successfully", }) } // CreateMessage handles creating a new message in a conversation func (h *ConversationHandler) CreateMessage(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get conversation ID from URL params conversationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse conversation ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid conversation ID", }) return } var req models.CreateMessageRequest if err := c.ShouldBindJSON(&req); err != nil { logger.WithError(err).Error("Failed to parse create message request") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid request body", }) return } // Create message message, err := h.conversationService.CreateMessage(uint(conversationID), userID.(uint), &req) if err != nil { logger.WithError(err).Error("Failed to create message") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to create message", }) return } c.JSON(http.StatusCreated, gin.H{ "success": true, "message": "Message created successfully", "data": gin.H{ "message": message, }, }) } // GetMessages handles getting messages in a conversation func (h *ConversationHandler) GetMessages(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get conversation ID from URL params conversationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse conversation ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid conversation ID", }) return } // Parse query parameters page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20")) if page < 1 { page = 1 } if pageSize < 1 || pageSize > 100 { pageSize = 20 } // Get messages response, err := h.conversationService.GetMessages(uint(conversationID), userID.(uint), page, pageSize) if err != nil { logger.WithError(err).Error("Failed to get messages") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to get messages", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "data": gin.H{ "messages": response.Messages, "total": response.Total, "page": response.Page, "pageSize": response.PageSize, }, }) } // UpdateMessage handles updating a message func (h *ConversationHandler) UpdateMessage(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get message ID from URL params messageID, err := strconv.ParseUint(c.Param("messageId"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse message ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid message ID", }) return } var req models.UpdateMessageRequest if err := c.ShouldBindJSON(&req); err != nil { logger.WithError(err).Error("Failed to parse update message request") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid request body", }) return } // Update message message, err := h.conversationService.UpdateMessage(uint(messageID), userID.(uint), &req) if err != nil { logger.WithError(err).Error("Failed to update message") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to update message", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Message updated successfully", "data": gin.H{ "message": message, }, }) } // DeleteMessage handles deleting a message func (h *ConversationHandler) DeleteMessage(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get message ID from URL params messageID, err := strconv.ParseUint(c.Param("messageId"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse message ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid message ID", }) return } // Delete message err = h.conversationService.DeleteMessage(uint(messageID), userID.(uint)) if err != nil { logger.WithError(err).Error("Failed to delete message") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to delete message", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Message deleted successfully", }) } // SendMessageWithAI handles sending a message and getting an AI response func (h *ConversationHandler) SendMessageWithAI(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get conversation ID from URL params conversationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse conversation ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid conversation ID", }) return } var req struct { Content string `json:"content" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { logger.WithError(err).Error("Failed to parse send message request") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid request body", }) return } // Send message and get AI response userMessage, aiMessage, err := h.conversationService.SendMessageWithAI(uint(conversationID), userID.(uint), req.Content) if err != nil { logger.WithError(err).Error("Failed to send message with AI") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to send message with AI", }) return } c.JSON(http.StatusCreated, gin.H{ "success": true, "message": "Message sent and AI response received", "data": gin.H{ "userMessage": userMessage, "aiMessage": aiMessage, }, }) } // GetConversationStats handles getting statistics for a conversation func (h *ConversationHandler) GetConversationStats(c *gin.Context) { // Get user ID from context userID, exists := c.Get("userID") if !exists { logger.Error("Failed to get user ID from context") c.JSON(http.StatusUnauthorized, gin.H{ "success": false, "message": "Unauthorized", }) return } // Get conversation ID from URL params conversationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { logger.WithError(err).Error("Failed to parse conversation ID") c.JSON(http.StatusBadRequest, gin.H{ "success": false, "message": "Invalid conversation ID", }) return } // Get conversation stats stats, err := h.conversationService.GetConversationStats(uint(conversationID), userID.(uint)) if err != nil { logger.WithError(err).Error("Failed to get conversation stats") c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "Failed to get conversation stats", }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "data": gin.H{ "stats": stats, }, }) }