package repository import ( "context" "database/sql" "errors" "fmt" "time" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" "github.com/jackc/pgx/v5/pgtype" ) func (s *Store) CreateUser(ctx context.Context, user domain.User, usedOtpId int64, is_company bool) (domain.User, error) { err := s.queries.MarkOtpAsUsed(ctx, dbgen.MarkOtpAsUsedParams{ ID: usedOtpId, UsedAt: pgtype.Timestamptz{ Time: time.Now(), Valid: true, }, }) if err != nil { return domain.User{}, err } userRes, err := s.queries.CreateUser(ctx, dbgen.CreateUserParams{ FirstName: user.FirstName, LastName: user.LastName, Email: pgtype.Text{ String: user.Email, Valid: user.Email != "", }, PhoneNumber: pgtype.Text{ String: user.PhoneNumber, Valid: user.PhoneNumber != "", }, Password: user.Password, Role: string(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: pgtype.Timestamptz{ Time: time.Now(), Valid: true, }, UpdatedAt: pgtype.Timestamptz{ Time: time.Now(), Valid: true, }, }) if err != nil { return domain.User{}, err } return domain.User{ ID: userRes.ID, FirstName: userRes.FirstName, LastName: userRes.LastName, Email: userRes.Email.String, PhoneNumber: userRes.PhoneNumber.String, Role: domain.Role(userRes.Role), }, nil } func (s *Store) GetUserByID(ctx context.Context, id int64) (domain.User, error) { user, err := s.queries.GetUserByID(ctx, id) if err != nil { if errors.Is(err, sql.ErrNoRows) { return domain.User{}, domain.ErrUserNotFound } return domain.User{}, err } return domain.User{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), EmailVerified: user.EmailVerified, Password: user.Password, PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, SuspendedAt: user.SuspendedAt.Time, Suspended: user.Suspended, }, nil } func (s *Store) GetAllUsers(ctx context.Context, filter user.Filter) ([]domain.User, int64, error) { users, err := s.queries.GetAllUsers(ctx, dbgen.GetAllUsersParams{ Role: filter.Role, CompanyID: pgtype.Int8{ Int64: filter.CompanyID.Value, Valid: filter.CompanyID.Valid, }, Limit: pgtype.Int4{ Int32: int32(filter.PageSize.Value), Valid: filter.PageSize.Valid, }, Offset: pgtype.Int4{ Int32: int32(filter.Page.Value), Valid: filter.Page.Valid, }, }) if err != nil { return nil, 0, err } userList := make([]domain.User, len(users)) for i, user := range users { userList[i] = domain.User{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, EmailVerified: user.EmailVerified, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, SuspendedAt: user.SuspendedAt.Time, Suspended: user.Suspended, } } totalCount, err := s.queries.GetTotalUsers(ctx, dbgen.GetTotalUsersParams{ Role: filter.Role, CompanyID: pgtype.Int8{ Int64: filter.CompanyID.Value, Valid: filter.CompanyID.Valid, }, }) return userList, totalCount, nil } func (s *Store) GetAllCashiers(ctx context.Context) ([]domain.GetCashier, error) { users, err := s.queries.GetAllCashiers(ctx) if err != nil { return nil, err } userList := make([]domain.GetCashier, len(users)) for i, user := range users { userList[i] = domain.GetCashier{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, SuspendedAt: user.SuspendedAt.Time, Suspended: user.Suspended, } } return userList, nil } func (s *Store) GetCashierByID(ctx context.Context, cashierID int64) (domain.GetCashier, error) { user, err := s.queries.GetCashierByID(ctx, cashierID) if err != nil { return domain.GetCashier{}, err } return domain.GetCashier{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, SuspendedAt: user.SuspendedAt.Time, Suspended: user.Suspended, BranchID: user.BranchID, }, nil } func (s *Store) GetCashiersByBranch(ctx context.Context, branchID int64) ([]domain.User, error) { users, err := s.queries.GetCashiersByBranch(ctx, branchID) if err != nil { return nil, err } userList := make([]domain.User, len(users)) for i, user := range users { userList[i] = domain.User{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, SuspendedAt: user.SuspendedAt.Time, Suspended: user.Suspended, } } return userList, nil } func (s *Store) SearchUserByNameOrPhone(ctx context.Context, searchString string, role *domain.Role, companyID domain.ValidInt64) ([]domain.User, error) { query := dbgen.SearchUserByNameOrPhoneParams{ Column1: pgtype.Text{ String: searchString, Valid: true, }, CompanyID: pgtype.Int8{ Int64: companyID.Value, Valid: companyID.Valid, }, } if role != nil { query.Role = pgtype.Text{ String: string(*role), Valid: true, } } users, err := s.queries.SearchUserByNameOrPhone(ctx, query) if err != nil { return nil, err } userList := make([]domain.User, 0, len(users)) for _, user := range users { userList = append(userList, domain.User{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, Suspended: user.Suspended, SuspendedAt: user.SuspendedAt.Time, }) } return userList, nil } func (s *Store) UpdateUser(ctx context.Context, user domain.UpdateUserReq) error { err := s.queries.UpdateUser(ctx, dbgen.UpdateUserParams{ ID: user.UserId, FirstName: user.FirstName.Value, LastName: user.LastName.Value, Suspended: user.Suspended.Value, }) fmt.Printf("Updating User %v with values %v", user.UserId, user) if err != nil { return err } return nil } func (s *Store) UpdateUserCompany(ctx context.Context, id int64, companyID int64) error { err := s.queries.UpdateUserCompany(ctx, dbgen.UpdateUserCompanyParams{ CompanyID: pgtype.Int8{ Int64: companyID, Valid: true, }, ID: id, }) if err != nil { return err } return nil } func (s *Store) UpdateUserSuspend(ctx context.Context, id int64, status bool) error { err := s.queries.SuspendUser(ctx, dbgen.SuspendUserParams{ ID: id, Suspended: status, SuspendedAt: pgtype.Timestamptz{ Time: time.Now(), Valid: true, }, }) if err != nil { return err } return nil } func (s *Store) DeleteUser(ctx context.Context, id int64) error { err := s.queries.DeleteUser(ctx, id) if err != nil { return err } return nil } func (s *Store) CheckPhoneEmailExist(ctx context.Context, phoneNum, email string) (bool, bool, error) { row, err := s.queries.CheckPhoneEmailExist(ctx, dbgen.CheckPhoneEmailExistParams{ PhoneNumber: pgtype.Text{ String: phoneNum, Valid: phoneNum != "", }, Email: pgtype.Text{ String: email, Valid: email != "", }, }) if err != nil { return false, false, err } return row.EmailExists, row.PhoneExists, nil } func (s *Store) GetUserByEmail(ctx context.Context, email string) (domain.User, error) { user, err := s.queries.GetUserByEmail(ctx, pgtype.Text{ String: email, Valid: true, }) if err != nil { if errors.Is(err, sql.ErrNoRows) { return domain.User{}, domain.ErrUserNotFound } return domain.User{}, err } return domain.User{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, Suspended: user.Suspended, SuspendedAt: user.SuspendedAt.Time, }, nil } func (s *Store) GetUserByPhone(ctx context.Context, phoneNum string) (domain.User, error) { user, err := s.queries.GetUserByPhone(ctx, pgtype.Text{ String: phoneNum, Valid: true, }) if err != nil { if errors.Is(err, sql.ErrNoRows) { return domain.User{}, domain.ErrUserNotFound } return domain.User{}, err } return domain.User{ ID: user.ID, FirstName: user.FirstName, LastName: user.LastName, Email: user.Email.String, PhoneNumber: user.PhoneNumber.String, Role: domain.Role(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: user.CreatedAt.Time, UpdatedAt: user.UpdatedAt.Time, Suspended: user.Suspended, SuspendedAt: user.SuspendedAt.Time, }, nil } func (s *Store) UpdatePassword(ctx context.Context, identifier string, password []byte, usedOtpId int64) error { err := s.queries.MarkOtpAsUsed(ctx, dbgen.MarkOtpAsUsedParams{ ID: usedOtpId, UsedAt: pgtype.Timestamptz{ Time: time.Now(), Valid: true, }, }) if err != nil { return err } err = s.queries.UpdatePassword(ctx, dbgen.UpdatePasswordParams{ Password: password, Email: pgtype.Text{ String: identifier, Valid: true, }, PhoneNumber: pgtype.Text{ String: identifier, Valid: true, }, }) if err != nil { return err } return nil } func (s *Store) CreateUserWithoutOtp(ctx context.Context, user domain.User, is_company bool) (domain.User, error) { userRes, err := s.queries.CreateUser(ctx, dbgen.CreateUserParams{ FirstName: user.FirstName, LastName: user.LastName, Email: pgtype.Text{ String: user.Email, Valid: user.Email != "", }, PhoneNumber: pgtype.Text{ String: user.PhoneNumber, Valid: user.PhoneNumber != "", }, Password: user.Password, Role: string(user.Role), EmailVerified: user.EmailVerified, PhoneVerified: user.PhoneVerified, CreatedAt: pgtype.Timestamptz{ Time: time.Now(), Valid: true, }, UpdatedAt: pgtype.Timestamptz{ Time: time.Now(), Valid: true, }, Suspended: user.Suspended, CompanyID: pgtype.Int8{ Int64: user.CompanyID.Value, Valid: user.CompanyID.Valid, }, }) if err != nil { return domain.User{}, err } return domain.User{ ID: userRes.ID, FirstName: userRes.FirstName, LastName: userRes.LastName, Email: userRes.Email.String, PhoneNumber: userRes.PhoneNumber.String, Role: domain.Role(userRes.Role), EmailVerified: userRes.EmailVerified, PhoneVerified: userRes.PhoneVerified, CreatedAt: userRes.CreatedAt.Time, UpdatedAt: userRes.UpdatedAt.Time, Suspended: userRes.Suspended, }, nil }