package team import ( "context" "time" "Yimaru-Backend/internal/domain" "golang.org/x/crypto/bcrypt" ) const bcryptCost = 10 func (s *Service) CreateTeamMember(ctx context.Context, req domain.CreateTeamMemberReq, createdBy *int64) (domain.TeamMember, error) { if !domain.TeamRole(req.TeamRole).IsValid() { return domain.TeamMember{}, domain.ErrInvalidTeamRole } if req.EmploymentType != "" && !domain.EmploymentType(req.EmploymentType).IsValid() { return domain.TeamMember{}, domain.ErrInvalidEmploymentType } exists, err := s.teamStore.CheckTeamMemberEmailExists(ctx, req.Email) if err != nil { return domain.TeamMember{}, err } if exists { return domain.TeamMember{}, domain.ErrTeamMemberEmailExists } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcryptCost) if err != nil { return domain.TeamMember{}, err } var hireDate *time.Time if req.HireDate != "" { parsed, err := time.Parse("2006-01-02", req.HireDate) if err != nil { return domain.TeamMember{}, err } hireDate = &parsed } member := domain.TeamMember{ FirstName: req.FirstName, LastName: req.LastName, Email: req.Email, PhoneNumber: req.PhoneNumber, Password: hashedPassword, TeamRole: domain.TeamRole(req.TeamRole), Department: req.Department, JobTitle: req.JobTitle, EmploymentType: domain.EmploymentType(req.EmploymentType), HireDate: hireDate, ProfilePictureURL: req.ProfilePictureURL, Bio: req.Bio, WorkPhone: req.WorkPhone, EmergencyContact: req.EmergencyContact, Status: domain.TeamMemberStatusActive, Permissions: req.Permissions, CreatedBy: createdBy, } return s.teamStore.CreateTeamMember(ctx, member) } func (s *Service) GetTeamMemberByID(ctx context.Context, id int64) (domain.TeamMember, error) { return s.teamStore.GetTeamMemberByID(ctx, id) } func (s *Service) GetTeamMemberByEmail(ctx context.Context, email string) (domain.TeamMember, error) { return s.teamStore.GetTeamMemberByEmail(ctx, email) } func (s *Service) GetAllTeamMembers(ctx context.Context, filter domain.TeamMemberFilter) ([]domain.TeamMember, int64, error) { var limit int32 = 10 var offset int32 = 0 if filter.PageSize > 0 { limit = int32(filter.PageSize) } if filter.Page > 0 && filter.PageSize > 0 { offset = int32((filter.Page - 1) * filter.PageSize) } return s.teamStore.GetAllTeamMembers(ctx, filter.TeamRole, filter.Department, filter.Status, limit, offset) } func (s *Service) SearchTeamMembers(ctx context.Context, search string, teamRole, status *string) ([]domain.TeamMember, error) { return s.teamStore.SearchTeamMembers(ctx, search, teamRole, status) } func (s *Service) UpdateTeamMember(ctx context.Context, req domain.UpdateTeamMemberReq) error { if req.TeamRole != "" && !domain.TeamRole(req.TeamRole).IsValid() { return domain.ErrInvalidTeamRole } if req.EmploymentType != "" && !domain.EmploymentType(req.EmploymentType).IsValid() { return domain.ErrInvalidEmploymentType } return s.teamStore.UpdateTeamMember(ctx, req) } func (s *Service) UpdateTeamMemberStatus(ctx context.Context, req domain.UpdateTeamMemberStatusReq) error { if !domain.TeamMemberStatus(req.Status).IsValid() { return domain.ErrInvalidTeamMemberStatus } return s.teamStore.UpdateTeamMemberStatus(ctx, req) } func (s *Service) DeleteTeamMember(ctx context.Context, memberID int64) error { return s.teamStore.DeleteTeamMember(ctx, memberID) } func (s *Service) GetTeamMemberStats(ctx context.Context) (domain.TeamMemberStats, error) { return s.teamStore.CountTeamMembersByStatus(ctx) } func (s *Service) Login(ctx context.Context, req domain.TeamMemberLoginReq) (domain.TeamMember, error) { member, err := s.teamStore.GetTeamMemberByEmail(ctx, req.Email) if err != nil { return domain.TeamMember{}, err } if err := bcrypt.CompareHashAndPassword(member.Password, []byte(req.Password)); err != nil { return domain.TeamMember{}, err } if err := s.teamStore.UpdateTeamMemberLastLogin(ctx, member.ID); err != nil { return domain.TeamMember{}, err } return member, nil } func (s *Service) ChangePassword(ctx context.Context, memberID int64, currentPassword, newPassword string) error { member, err := s.teamStore.GetTeamMemberByID(ctx, memberID) if err != nil { return err } if err := bcrypt.CompareHashAndPassword(member.Password, []byte(currentPassword)); err != nil { return err } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcryptCost) if err != nil { return err } return s.teamStore.UpdateTeamMemberPassword(ctx, memberID, string(hashedPassword)) } func (s *Service) ResetPassword(ctx context.Context, memberID int64, newPassword string) error { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcryptCost) if err != nil { return err } return s.teamStore.UpdateTeamMemberPassword(ctx, memberID, string(hashedPassword)) }