Files
AI-Support/backend/internal/handlers/conversation.go
2025-09-13 06:48:55 +03:00

559 lines
14 KiB
Go

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,
},
})
}