package handlers import ( "context" "fmt" "net/http" apperrors "veza-backend-api/internal/errors" "veza-backend-api/internal/models" "veza-backend-api/internal/services" "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" ) // ChatServiceInterfaceForChatHandler defines methods needed for chat handler type ChatServiceInterfaceForChatHandler interface { GenerateToken(userID uuid.UUID, username string) (*services.ChatTokenResponse, error) GetStats(ctx context.Context) (*services.ChatStats, error) } // UserServiceInterfaceForChatHandler defines methods needed for chat handler type UserServiceInterfaceForChatHandler interface { GetByID(userID uuid.UUID) (*models.User, error) } type ChatHandler struct { chatService ChatServiceInterfaceForChatHandler userService UserServiceInterfaceForChatHandler logger *zap.Logger } func NewChatHandler(chatService *services.ChatService, userService *services.UserService, logger *zap.Logger) *ChatHandler { return &ChatHandler{ chatService: &chatServiceWrapper{chatService: chatService}, userService: &userServiceWrapper{userService: userService}, logger: logger, } } // chatServiceWrapper wraps *services.ChatService to implement ChatServiceInterfaceForChatHandler type chatServiceWrapper struct { chatService *services.ChatService } func (w *chatServiceWrapper) GenerateToken(userID uuid.UUID, username string) (*services.ChatTokenResponse, error) { return w.chatService.GenerateToken(userID, username) } func (w *chatServiceWrapper) GetStats(ctx context.Context) (*services.ChatStats, error) { return w.chatService.GetStats(ctx) } // userServiceWrapper wraps *services.UserService to implement UserServiceInterfaceForChatHandler type userServiceWrapper struct { userService *services.UserService } func (w *userServiceWrapper) GetByID(userID uuid.UUID) (*models.User, error) { return w.userService.GetByID(userID) } // NewChatHandlerWithInterface creates a new chat handler with interfaces (for testing) func NewChatHandlerWithInterface(chatService ChatServiceInterfaceForChatHandler, userService UserServiceInterfaceForChatHandler, logger *zap.Logger) *ChatHandler { return &ChatHandler{ chatService: chatService, userService: userService, logger: logger, } } // GetToken generates a JWT token for the chat service // @Summary Get Chat Token // @Description Generate a short-lived token for chat authentication // @Tags Chat // @Accept json // @Produce json // @Security BearerAuth // @Success 200 {object} APIResponse{data=object{token=string}} // @Failure 401 {object} APIResponse "Unauthorized" // @Failure 500 {object} APIResponse "Internal Error" // @Router /chat/token [get] func (h *ChatHandler) GetToken(c *gin.Context) { userIDVal, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } userID, ok := userIDVal.(uuid.UUID) if !ok || userID == uuid.Nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } // Get username from DB user, err := h.userService.GetByID(userID) username := "user" if err == nil && user != nil { username = user.Username } else { // Fallback username = fmt.Sprintf("user_%s", userID) } token, err := h.chatService.GenerateToken(userID, username) if err != nil { h.logger.Error("Failed to generate chat token", zap.Error(err)) c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"}) return } RespondSuccess(c, http.StatusOK, token) } // GetStats returns chat statistics // BE-API-006: Implement chat stats endpoint func (h *ChatHandler) GetStats(c *gin.Context) { stats, err := h.chatService.GetStats(c.Request.Context()) if err != nil { h.logger.Error("Failed to get chat stats", zap.Error(err)) RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to get chat stats", err)) return } RespondSuccess(c, http.StatusOK, stats) }