package handlers import ( "log/slog" "time" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/user" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/gofiber/fiber/v2" ) type CreateAdminReq struct { FirstName string `json:"first_name" example:"John"` LastName string `json:"last_name" example:"Doe"` Email string `json:"email" example:"john.doe@example.com"` PhoneNumber string `json:"phone_number" example:"1234567890"` Password string `json:"password" example:"password123"` CompanyID *int64 `json:"company_id,omitempty" example:"1"` } // CreateAdmin godoc // @Summary Create Admin // @Description Create Admin // @Tags admin // @Accept json // @Produce json // @Param manger body CreateAdminReq true "Create admin" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /admin [post] func (h *Handler) CreateAdmin(c *fiber.Ctx) error { var companyID domain.ValidInt64 var req CreateAdminReq if err := c.BodyParser(&req); err != nil { h.logger.Error("RegisterUser failed", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", err, nil) } valErrs, ok := h.validator.Validate(c, req) if !ok { return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) } // Admins can be created without company ids and can be assigned later if req.CompanyID == nil { companyID = domain.ValidInt64{ Value: 0, Valid: false, } } else { _, err := h.companySvc.GetCompanyByID(c.Context(), *req.CompanyID) if err != nil { h.logger.Error("CreateAdmin company id is invalid", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Company ID is invalid", nil, nil) } companyID = domain.ValidInt64{ Value: *req.CompanyID, Valid: true, } } user := domain.CreateUserReq{ FirstName: req.FirstName, LastName: req.LastName, Email: req.Email, PhoneNumber: req.PhoneNumber, Password: req.Password, Role: string(domain.RoleAdmin), CompanyID: companyID, } h.logger.Info("CreateAdmin", slog.Bool("company id", req.CompanyID == nil)) newUser, err := h.userSvc.CreateUser(c.Context(), user, true) if err != nil { h.logger.Error("CreateAdmin failed", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create admin", nil, nil) } if req.CompanyID != nil { _, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{ ID: *req.CompanyID, AdminID: &newUser.ID, }) if err != nil { h.logger.Error("CreateAdmin failed to update company", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", nil, nil) } } return response.WriteJSON(c, fiber.StatusOK, "Admin created successfully", nil, nil) } type AdminRes struct { ID int64 `json:"id"` FirstName string `json:"first_name"` LastName string `json:"last_name"` Email string `json:"email"` PhoneNumber string `json:"phone_number"` Role domain.Role `json:"role"` EmailVerified bool `json:"email_verified"` PhoneVerified bool `json:"phone_verified"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` LastLogin time.Time `json:"last_login"` SuspendedAt time.Time `json:"suspended_at"` Suspended bool `json:"suspended"` } // GetAllAdmins godoc // @Summary Get all Admins // @Description Get all Admins // @Tags admin // @Accept json // @Produce json // @Param page query int false "Page number" // @Param page_size query int false "Page size" // @Success 200 {object} AdminRes // @Failure 400 {object} response.APIResponse // @Failure 401 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /admin [get] func (h *Handler) GetAllAdmins(c *fiber.Ctx) error { filter := user.Filter{ Role: string(domain.RoleAdmin), CompanyID: domain.ValidInt64{ Value: int64(c.QueryInt("company_id")), Valid: true, }, Page: c.QueryInt("page", 1) - 1, PageSize: c.QueryInt("page_size", 10), } valErrs, ok := h.validator.Validate(c, filter) if !ok { return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) } admins, total, err := h.userSvc.GetAllUsers(c.Context(), filter) if err != nil { h.logger.Error("GetAllAdmins failed", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Admins", nil, nil) } var result []AdminRes = make([]AdminRes, len(admins)) for index, admin := range admins { lastLogin, err := h.authSvc.GetLastLogin(c.Context(), admin.ID) if err != nil { if err == authentication.ErrRefreshTokenNotFound { lastLogin = &admin.CreatedAt } else { h.logger.Error("Failed to get user last login", "userID", admin.ID, "error", err) return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login") } } result[index] = AdminRes{ ID: admin.ID, FirstName: admin.FirstName, LastName: admin.LastName, Email: admin.Email, PhoneNumber: admin.PhoneNumber, Role: admin.Role, EmailVerified: admin.EmailVerified, PhoneVerified: admin.PhoneVerified, CreatedAt: admin.CreatedAt, UpdatedAt: admin.UpdatedAt, SuspendedAt: admin.SuspendedAt, Suspended: admin.Suspended, LastLogin: *lastLogin, } } return response.WritePaginatedJSON(c, fiber.StatusOK, "Admins retrieved successfully", result, nil, filter.Page, int(total)) }