package handler import ( "errors" "net/http" "github.com/gin-gonic/gin" "dating-app/internal/dto" "dating-app/internal/service" "dating-app/internal/utils" ) type AuthHandler struct { authService *service.AuthService } func NewAuthHandler(authService *service.AuthService) *AuthHandler { return &AuthHandler{authService: authService} } // RequestOTP POST /auth/request-otp func (h *AuthHandler) RequestOTP(c *gin.Context) { var req dto.RequestOTPRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } err := h.authService.RequestOTP(req.Phone) if err != nil { var stillValid *service.OTPStillValidError switch { case errors.As(err, &stillValid): utils.Fail(c, http.StatusTooManyRequests, "کد تایید قبلی هنوز معتبر است", gin.H{"remaining_seconds": stillValid.RemainingSeconds}) case errors.Is(err, service.ErrPhoneBlocked): utils.Fail(c, http.StatusForbidden, err.Error(), nil) case errors.Is(err, service.ErrSMSSendFailed): utils.Fail(c, http.StatusServiceUnavailable, err.Error(), nil) default: utils.Fail(c, http.StatusBadRequest, err.Error(), nil) } return } utils.Success(c, http.StatusOK, "کد تایید با موفقیت ارسال شد", nil) } // VerifyOTP POST /auth/verify-otp func (h *AuthHandler) VerifyOTP(c *gin.Context) { var req dto.VerifyOTPRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } user, access, refresh, isNew, err := h.authService.VerifyOTP(req.Phone, req.OTP) if err != nil { switch { case errors.Is(err, service.ErrUserNotFound): utils.Fail(c, http.StatusNotFound, err.Error(), nil) case errors.Is(err, service.ErrOTPExpired), errors.Is(err, service.ErrOTPInvalid), errors.Is(err, service.ErrOTPNotRequested): utils.Fail(c, http.StatusBadRequest, err.Error(), nil) default: utils.Fail(c, http.StatusInternalServerError, "خطای داخلی سرور", nil) } return } utils.Success(c, http.StatusOK, "ورود با موفقیت انجام شد", dto.AuthResponse{ Tokens: dto.TokenPair{ AccessToken: access, RefreshToken: refresh, }, User: toUserProfile(user), IsNewUser: isNew, OnboardingDone: user.IsOnboarded, }) } // RefreshToken POST /auth/token/refresh func (h *AuthHandler) RefreshToken(c *gin.Context) { var req dto.RefreshTokenRequest if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, http.StatusBadRequest, "ورودی نامعتبر است", err.Error()) return } access, refresh, err := h.authService.RefreshTokens(req.RefreshToken) if err != nil { utils.Fail(c, http.StatusUnauthorized, "رفرش توکن نامعتبر یا منقضی شده است", nil) return } utils.Success(c, http.StatusOK, "توکن جدید صادر شد", dto.TokenPair{ AccessToken: access, RefreshToken: refresh, }) }