package services // import ( // "errors" // "fmt" // "math/rand" // "rijig/config" // "rijig/dto" // "rijig/internal/repositories" // "rijig/model" // "rijig/utils" // "time" // "github.com/golang-jwt/jwt/v5" // ) // const otpCooldown = 30 * time.Second // type AuthService interface { // RegisterOrLogin(req *dto.RegisterRequest) error // VerifyOTP(req *dto.VerifyOTPRequest) (*dto.UserDataResponse, error) // Logout(userID, phone string) error // } // type authService struct { // userRepo repositories.UserRepository // roleRepo repositories.RoleRepository // } // func NewAuthService(userRepo repositories.UserRepository, roleRepo repositories.RoleRepository) AuthService { // return &authService{userRepo, roleRepo} // } // func (s *authService) RegisterOrLogin(req *dto.RegisterRequest) error { // if err := s.checkOTPRequestCooldown(req.Phone); err != nil { // return err // } // user, err := s.userRepo.GetUserByPhoneAndRole(req.Phone, req.RoleID) // if err != nil { // return fmt.Errorf("failed to check existing user: %w", err) // } // if user != nil { // return s.sendOTP(req.Phone) // } // user = &model.User{ // Phone: req.Phone, // RoleID: req.RoleID, // } // createdUser, err := s.userRepo.CreateUser(user) // if err != nil { // return fmt.Errorf("failed to create new user: %w", err) // } // if err := s.saveUserToRedis(createdUser.ID, createdUser, req.Phone); err != nil { // return err // } // return s.sendOTP(req.Phone) // } // func (s *authService) checkOTPRequestCooldown(phone string) error { // otpSentTime, err := utils.GetStringData("otp_sent:" + phone) // if err != nil || otpSentTime == "" { // return nil // } // lastSent, _ := time.Parse(time.RFC3339, otpSentTime) // if time.Since(lastSent) < otpCooldown { // return errors.New("please wait before requesting a new OTP") // } // return nil // } // func (s *authService) sendOTP(phone string) error { // otp := generateOTP() // if err := config.SendWhatsAppMessage(phone, fmt.Sprintf("Your OTP is: %s", otp)); err != nil { // return err // } // if err := utils.SetStringData("otp:"+phone, otp, 10*time.Minute); err != nil { // return err // } // return utils.SetStringData("otp_sent:"+phone, time.Now().Format(time.RFC3339), 10*time.Minute) // } // func (s *authService) VerifyOTP(req *dto.VerifyOTPRequest) (*dto.UserDataResponse, error) { // storedOTP, err := utils.GetStringData("otp:" + req.Phone) // if err != nil || storedOTP == "" { // return nil, errors.New("OTP expired or not found") // } // if storedOTP != req.OTP { // return nil, errors.New("invalid OTP") // } // if err := utils.DeleteData("otp:" + req.Phone); err != nil { // return nil, fmt.Errorf("failed to remove OTP from Redis: %w", err) // } // existingUser, err := s.userRepo.GetUserByPhoneAndRole(req.Phone, req.RoleID) // if err != nil { // return nil, fmt.Errorf("failed to check existing user: %w", err) // } // var user *model.User // if existingUser != nil { // user = existingUser // } else { // user = &model.User{ // Phone: req.Phone, // RoleID: req.RoleID, // } // createdUser, err := s.userRepo.CreateUser(user) // if err != nil { // return nil, err // } // user = createdUser // } // token, err := s.generateJWTToken(user.ID) // if err != nil { // return nil, err // } // role, err := s.roleRepo.FindByID(user.RoleID) // if err != nil { // return nil, fmt.Errorf("failed to get role: %w", err) // } // if err := s.saveSessionData(user.ID, user.RoleID, role.RoleName, token); err != nil { // return nil, err // } // return &dto.UserDataResponse{ // UserID: user.ID, // UserRole: role.RoleName, // Token: token, // }, nil // } // func (s *authService) saveUserToRedis(userID string, user *model.User, phone string) error { // if err := utils.SetJSONData("user:"+userID, user, 10*time.Minute); err != nil { // return fmt.Errorf("failed to store user data in Redis: %w", err) // } // if err := utils.SetStringData("user_phone:"+userID, phone, 10*time.Minute); err != nil { // return fmt.Errorf("failed to store user phone in Redis: %w", err) // } // return nil // } // func (s *authService) generateJWTToken(userID string) (string, error) { // expirationTime := time.Now().Add(24 * time.Hour) // claims := &jwt.RegisteredClaims{ // Subject: userID, // ExpiresAt: jwt.NewNumericDate(expirationTime), // } // token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // secretKey := config.GetSecretKey() // return token.SignedString([]byte(secretKey)) // } // func (s *authService) saveSessionData(userID string, roleID string, roleName string, token string) error { // sessionKey := fmt.Sprintf("session:%s", userID) // sessionData := map[string]interface{}{ // "userID": userID, // "roleID": roleID, // "roleName": roleName, // } // if err := utils.SetJSONData(sessionKey, sessionData, 24*time.Hour); err != nil { // return fmt.Errorf("failed to set session data: %w", err) // } // if err := utils.SetStringData("session_token:"+userID, token, 24*time.Hour); err != nil { // return fmt.Errorf("failed to set session token: %w", err) // } // return nil // } // func (s *authService) Logout(userID, phone string) error { // keys := []string{ // "session:" + userID, // "session_token:" + userID, // "user_logged_in:" + userID, // "user:" + userID, // "user_phone:" + userID, // "otp_sent:" + phone, // } // for _, key := range keys { // if err := utils.DeleteData(key); err != nil { // return fmt.Errorf("failed to delete key %s from Redis: %w", key, err) // } // } // return nil // } // func generateOTP() string { // randGenerator := rand.New(rand.NewSource(time.Now().UnixNano())) // return fmt.Sprintf("%04d", randGenerator.Intn(10000)) // }