package handlers import ( "strconv" "time" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" "github.com/gofiber/fiber/v2" ) type CreateCompanyReq struct { Name string `json:"name" example:"CompanyName"` AdminID int64 `json:"admin_id" example:"1"` } type UpdateCompanyReq struct { Name *string `json:"name,omitempty" example:"CompanyName"` AdminID *int64 `json:"admin_id,omitempty" example:"1"` } type CompanyRes struct { ID int64 `json:"id" example:"1"` Name string `json:"name" example:"CompanyName"` AdminID int64 `json:"admin_id" example:"1"` WalletID int64 `json:"wallet_id" example:"1"` } type GetCompanyRes struct { ID int64 `json:"id" example:"1"` Name string `json:"name" example:"CompanyName"` AdminID int64 `json:"admin_id" example:"1"` WalletID int64 `json:"wallet_id" example:"1"` WalletBalance float32 `json:"balance" example:"1"` IsActive bool `json:"is_active" example:"false"` AdminFirstName string `json:"admin_first_name" example:"John"` AdminLastName string `json:"admin_last_name" example:"Doe"` AdminPhoneNumber string `json:"admin_phone_number" example:"1234567890"` } func convertCompany(company domain.Company) CompanyRes { return CompanyRes{ ID: company.ID, Name: company.Name, AdminID: company.AdminID, WalletID: company.WalletID, } } func convertGetCompany(company domain.GetCompany) GetCompanyRes { return GetCompanyRes{ ID: company.ID, Name: company.Name, AdminID: company.AdminID, WalletID: company.WalletID, WalletBalance: company.WalletBalance.Float32(), IsActive: company.IsWalletActive, AdminFirstName: company.AdminFirstName, AdminLastName: company.AdminLastName, AdminPhoneNumber: company.AdminPhoneNumber, } } // CreateCompany godoc // @Summary Create a company // @Description Creates a company // @Tags company // @Accept json // @Produce json // @Param createCompany body CreateCompanyReq true "Creates company" // @Success 200 {object} CompanyRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /company [post] func (h *Handler) CreateCompany(c *fiber.Ctx) error { var req CreateCompanyReq if err := c.BodyParser(&req); err != nil { h.logger.Error("CreateCompanyReq 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) } user, err := h.userSvc.GetUserByID(c.Context(), req.AdminID) if err != nil { h.logger.Error("Error fetching user", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get user", err, nil) } // Create Company Wallet newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{ IsWithdraw: false, IsBettable: true, IsTransferable: true, UserID: req.AdminID, }) if err != nil { h.logger.Error("Create Company Wallet failed", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create company wallet", err, nil) } company, err := h.companySvc.CreateCompany(c.Context(), domain.CreateCompany{ Name: req.Name, AdminID: user.ID, WalletID: newWallet.ID, }) if err != nil { h.logger.Error("CreateCompanyReq failed", "error", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", }) } err = h.userSvc.UpdateUserCompany(c.Context(), user.ID, company.ID) if err != nil { h.logger.Error("CreateCompanyReq failed", "error", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", }) } res := convertCompany(company) return response.WriteJSON(c, fiber.StatusCreated, "Company Created", res, nil) } // GetAllCompanies godoc // @Summary Gets all companies // @Description Gets all companies // @Tags company // @Accept json // @Produce json // @Success 200 {array} CompanyRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /company [get] func (h *Handler) GetAllCompanies(c *fiber.Ctx) error { searchQuery := c.Query("query") searchString := domain.ValidString{ Value: searchQuery, Valid: searchQuery != "", } createdBeforeQuery := c.Query("created_before") var createdBefore domain.ValidTime if createdBeforeQuery != "" { createdBeforeParsed, err := time.Parse(time.RFC3339, createdBeforeQuery) if err != nil { h.logger.Error("invalid start_time format", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil) } createdBefore = domain.ValidTime{ Value: createdBeforeParsed, Valid: true, } } createdAfterQuery := c.Query("created_after") var createdAfter domain.ValidTime if createdAfterQuery != "" { createdAfterParsed, err := time.Parse(time.RFC3339, createdAfterQuery) if err != nil { h.logger.Error("invalid start_time format", "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid start_time format", nil, nil) } createdAfter = domain.ValidTime{ Value: createdAfterParsed, Valid: true, } } companies, err := h.companySvc.GetAllCompanies(c.Context(), domain.CompanyFilter{ Query: searchString, CreatedBefore: createdBefore, CreatedAfter: createdAfter, }) if err != nil { h.logger.Error("Failed to get companies", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil) } var result []GetCompanyRes = make([]GetCompanyRes, 0, len(companies)) for _, company := range companies { result = append(result, convertGetCompany(company)) } return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil) } // GetCompanyByID godoc // @Summary Gets company by id // @Description Gets a single company by id // @Tags company // @Accept json // @Produce json // @Param id path int true "Company ID" // @Success 200 {object} CompanyRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /company/{id} [get] func (h *Handler) GetCompanyByID(c *fiber.Ctx) error { companyID := c.Params("id") id, err := strconv.ParseInt(companyID, 10, 64) if err != nil { h.logger.Error("Invalid company ID", "companyID", companyID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil) } company, err := h.companySvc.GetCompanyByID(c.Context(), id) if err != nil { h.logger.Error("Failed to get company by ID", "companyID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil) } res := convertGetCompany(company) return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil) } // GetCompanyForAdmin godoc // @Summary Gets company by id // @Description Gets a single company by id // @Tags company // @Accept json // @Produce json // @Success 200 {object} CompanyRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /admin-company [get] func (h *Handler) GetCompanyForAdmin(c *fiber.Ctx) error { companyID := c.Locals("company_id").(domain.ValidInt64) if !companyID.Valid { return response.WriteJSON(c, fiber.StatusInternalServerError, "Invalid company ID", nil, nil) } company, err := h.companySvc.GetCompanyByID(c.Context(), companyID.Value) if err != nil { h.logger.Error("Failed to get company by ID", "companyID", companyID.Value, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to company branch", err, nil) } res := convertGetCompany(company) return response.WriteJSON(c, fiber.StatusOK, "Company retrieved successfully", res, nil) } // GetAllCompanies godoc // @Summary Gets all companies // @Description Gets all companies // @Tags company // @Accept json // @Produce json // @Success 200 {array} CompanyRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /search/company [get] func (h *Handler) SearchCompany(c *fiber.Ctx) error { searchQuery := c.Query("q") if searchQuery == "" { return response.WriteJSON(c, fiber.StatusBadRequest, "Search query is required", nil, nil) } companies, err := h.companySvc.SearchCompanyByName(c.Context(), searchQuery) if err != nil { h.logger.Error("Failed to get companies", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get companies", err, nil) } var result []GetCompanyRes = make([]GetCompanyRes, 0, len(companies)) for _, company := range companies { result = append(result, convertGetCompany(company)) } return response.WriteJSON(c, fiber.StatusOK, "All Companies retrieved", result, nil) } // UpdateCompany godoc // @Summary Updates a company // @Description Updates a company // @Tags company // @Accept json // @Produce json // @Param id path int true "Company ID" // @Param updateCompany body UpdateCompanyReq true "Update Company" // @Success 200 {object} CompanyRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /company/{id} [put] func (h *Handler) UpdateCompany(c *fiber.Ctx) error { companyID := c.Params("id") id, err := strconv.ParseInt(companyID, 10, 64) if err != nil { h.logger.Error("Invalid company ID", "companyID", companyID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil) } var req UpdateCompanyReq if err := c.BodyParser(&req); err != nil { h.logger.Error("UpdateCompanyReq 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) } company, err := h.companySvc.UpdateCompany(c.Context(), domain.UpdateCompany{ ID: id, Name: req.Name, AdminID: req.AdminID, }) if err != nil { h.logger.Error("Failed to update company", "companyID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update company", err, nil) } res := convertCompany(company) return response.WriteJSON(c, fiber.StatusOK, "Company Updated", res, nil) } // DeleteCompany godoc // @Summary Delete the company // @Description Delete the company // @Tags company // @Accept json // @Produce json // @Param id path int true "Company ID"" // @Success 200 {object} response.APIResponse // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /company/{id} [delete] func (h *Handler) DeleteCompany(c *fiber.Ctx) error { companyID := c.Params("id") id, err := strconv.ParseInt(companyID, 10, 64) if err != nil { h.logger.Error("Invalid Company ID", "companyID", companyID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Company ID", err, nil) } err = h.companySvc.DeleteCompany(c.Context(), id) if err != nil { h.logger.Error("Failed to delete by ID", "Company ID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Company", err, nil) } return response.WriteJSON(c, fiber.StatusOK, "Company removed successfully", nil, nil) }