package handlers import ( "net/http" "attune-heart-therapy/internal/middleware" "attune-heart-therapy/internal/services" "github.com/gin-gonic/gin" ) type AuthHandler struct { userService services.UserService } func NewAuthHandler(userService services.UserService) *AuthHandler { return &AuthHandler{ userService: userService, } } // Register handles POST /api/auth/register for new user registration func (h *AuthHandler) Register(c *gin.Context) { var req services.RegisterRequest // Bind JSON request to struct if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid request format", "details": err.Error(), }) return } // Create new user user, err := h.userService.Register(req) if err != nil { // Check for specific error types if err.Error() == "validation failed" || err.Error() == "password must be at least 8 characters long" { c.JSON(http.StatusBadRequest, gin.H{ "error": "Validation failed", "details": err.Error(), }) return } if err.Error() == "user with email "+req.Email+" already exists" { c.JSON(http.StatusConflict, gin.H{ "error": "User already exists", "details": err.Error(), }) return } c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create user", "details": err.Error(), }) return } c.JSON(http.StatusCreated, gin.H{ "message": "User registered successfully", "user": user, }) } // Login handles POST /api/auth/login for user authentication func (h *AuthHandler) Login(c *gin.Context) { var loginReq struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required"` } // Bind JSON request to struct if err := c.ShouldBindJSON(&loginReq); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid request format", "details": err.Error(), }) return } // Authenticate user user, token, err := h.userService.Login(loginReq.Email, loginReq.Password) if err != nil { if err.Error() == "invalid credentials" { c.JSON(http.StatusUnauthorized, gin.H{ "error": "Invalid email or password", }) return } c.JSON(http.StatusInternalServerError, gin.H{ "error": "Login failed", "details": err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "message": "Login successful", "user": user, "token": token, }) } // GetProfile handles GET /api/auth/profile for retrieving user profile func (h *AuthHandler) GetProfile(c *gin.Context) { // Get user ID from JWT token (set by auth middleware) userID, exists := middleware.GetUserIDFromContext(c) if !exists { c.JSON(http.StatusUnauthorized, gin.H{ "error": "User not authenticated", }) return } // Get user profile user, err := h.userService.GetProfile(userID) if err != nil { c.JSON(http.StatusNotFound, gin.H{ "error": "User not found", "details": err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "user": user, }) } // UpdateProfile handles PUT /api/auth/profile for updating user profile func (h *AuthHandler) UpdateProfile(c *gin.Context) { // Get user ID from JWT token (set by auth middleware) userID, exists := middleware.GetUserIDFromContext(c) if !exists { c.JSON(http.StatusUnauthorized, gin.H{ "error": "User not authenticated", }) return } var req services.UpdateProfileRequest // Bind JSON request to struct if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid request format", "details": err.Error(), }) return } // Update user profile user, err := h.userService.UpdateProfile(userID, req) if err != nil { if err.Error() == "invalid user ID" { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid user ID", }) return } c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update profile", "details": err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "message": "Profile updated successfully", "user": user, }) } // Logout handles POST /api/auth/logout for user logout // Note: Since we're using stateless JWT tokens, logout is handled client-side // by removing the token. This endpoint is provided for consistency. func (h *AuthHandler) Logout(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Logout successful", }) }