package handlers import ( "log/slog" "strconv" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator" "github.com/gofiber/fiber/v2" ) type CreateBranchReq struct { Name string `json:"name" example:"4-kilo Branch"` Location string `json:"location" example:"Addis Ababa"` WalletID int64 `json:"wallet_id" example:"1"` BranchManagerID int64 `json:"branch_manager_id" example:"1"` CompanyID int64 `json:"company_id" example:"1"` IsSelfOwned bool `json:"is_self_owned" example:"false"` } type CreateSupportedOperationReq struct { Name string `json:"name" example:"SportsBook"` Description string `json:"description" example:"Betting on sport events"` } type SupportedOperationRes struct { ID int64 `json:"id" example:"1"` Name string `json:"name" example:"SportsBook"` Description string `json:"description" example:"Betting on sport events"` } type CreateBranchOperationReq struct { BranchID int64 `json:"branch_id" example:"1"` OperationID int64 `json:"operation_id" example:"1"` } type BranchOperationRes struct { Name string `json:"name" example:"SportsBook"` Description string `json:"description" example:"Betting on sport events"` } type BranchRes struct { Name string `json:"name" example:"4-kilo Branch"` Location string `json:"location" example:"Addis Ababa"` WalletID int64 `json:"wallet_id" example:"1"` BranchManagerID int64 `json:"branch_manager_id" example:"1"` CompanyID int64 `json:"company_id" example:"1"` IsSelfOwned bool `json:"is_self_owned" example:"false"` } type BranchDetailRes struct { Name string `json:"name" example:"4-kilo Branch"` Location string `json:"location" example:"Addis Ababa"` WalletID int64 `json:"wallet_id" example:"1"` BranchManagerID int64 `json:"branch_manager_id" example:"1"` CompanyID int64 `json:"company_id" example:"1"` IsSelfOwned bool `json:"is_self_owned" example:"false"` ManagerName string `json:"manager_name" example:"John Smith"` ManagerPhoneNumber string `json:"manager_phone_number" example:"0911111111"` } func convertBranch(branch domain.Branch) BranchRes { return BranchRes{ Name: branch.Name, Location: branch.Location, WalletID: branch.WalletID, BranchManagerID: branch.BranchManagerID, CompanyID: branch.CompanyID, IsSelfOwned: branch.IsSelfOwned, } } func convertBranchDetail(branch domain.BranchDetail) BranchDetailRes { return BranchDetailRes{ Name: branch.Name, Location: branch.Location, WalletID: branch.WalletID, BranchManagerID: branch.BranchManagerID, CompanyID: branch.CompanyID, IsSelfOwned: branch.IsSelfOwned, ManagerName: branch.ManagerName, ManagerPhoneNumber: branch.ManagerPhoneNumber, } } func CreateBranch(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { // Check if user is either branch manager / super main // role := string(c.Locals("role").(domain.Role)) // if role != string(domain.RoleCustomer) { // logger.Error("Unauthorized access", "role", role) // return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil) // } var req CreateBranchReq if err := c.BodyParser(&req); err != nil { logger.Error("CreateBranchReq failed", "error", err) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Invalid request", }) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } branch, err := branchSvc.CreateBranch(c.Context(), domain.CreateBranch{ Name: req.Name, Location: req.Location, WalletID: req.WalletID, BranchManagerID: req.BranchManagerID, CompanyID: req.CompanyID, IsSelfOwned: req.IsSelfOwned, }) if err != nil { logger.Error("CreateBranchReq failed", "error", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", }) } res := convertBranch(branch) return response.WriteJSON(c, fiber.StatusOK, "Branch Created", res, nil) } } func CreateSupportedOperation(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { var req CreateSupportedOperationReq if err := c.BodyParser(&req); err != nil { logger.Error("CreateBranchReq failed", "error", err) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Invalid request", }) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } operation, err := branchSvc.CreateSupportedOperation(c.Context(), domain.CreateSupportedOperation{ Name: req.Name, Description: req.Description, }) if err != nil { logger.Error("CreateSupportedOperationReq failed", "error", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "error": "Internal server error", }) } res := SupportedOperationRes{ Name: operation.Name, Description: operation.Description, } return response.WriteJSON(c, fiber.StatusOK, "Operation Created", res, nil) } } func CreateBranchOperation(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { var req CreateBranchOperationReq if err := c.BodyParser(&req); err != nil { logger.Error("CreateBranchOperationReq failed", "error", err) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Invalid request", }) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } err := branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{ BranchID: req.BranchID, OperationID: req.OperationID, }) if err != nil { logger.Error("CreateBranchOperationReq failed", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Internal Server Error", err, nil) } return response.WriteJSON(c, fiber.StatusOK, "Branch Operation Created", nil, nil) } } func GetBranchByID(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { branchID := c.Params("id") id, err := strconv.ParseInt(branchID, 10, 64) if err != nil { logger.Error("Invalid branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil) } branch, err := branchSvc.GetBranchByID(c.Context(), id) if err != nil { logger.Error("Failed to get branch by ID", "branchID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve branch", err, nil) } res := convertBranchDetail(branch) return response.WriteJSON(c, fiber.StatusOK, "Branch retrieved successfully", res, nil) } } // /user/:id/branch func GetBranchByManagerID(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { userID := c.Params("id") id, err := strconv.ParseInt(userID, 10, 64) if err != nil { logger.Error("Invalid user ID", "userID", userID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid user ID", err, nil) } branches, err := branchSvc.GetBranchByManagerID(c.Context(), id) if err != nil { logger.Error("Failed to get branches", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil) } var result []BranchDetailRes = make([]BranchDetailRes, len(branches)) for _, branch := range branches { result = append(result, convertBranchDetail(branch)) } return response.WriteJSON(c, fiber.StatusOK, "Branches for Branch Manager retrieved", result, nil) } } // /company/:id/branch func GetBranchByCompanyID(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { companyID := c.Params("id") id, err := strconv.ParseInt(companyID, 10, 64) if err != nil { logger.Error("Invalid company ID", "companyID", companyID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid company ID", err, nil) } branches, err := branchSvc.GetBranchByCompanyID(c.Context(), id) if err != nil { logger.Error("Failed to get branches", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil) } var result []BranchDetailRes = make([]BranchDetailRes, len(branches)) for _, branch := range branches { result = append(result, convertBranchDetail(branch)) } return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil) } } func GetAllBranches(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { branches, err := branchSvc.GetAllBranches(c.Context()) if err != nil { logger.Error("Failed to get branches", "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get branches", err, nil) } var result []BranchDetailRes = make([]BranchDetailRes, len(branches)) for _, branch := range branches { result = append(result, convertBranchDetail(branch)) } return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil) } } func GetBranchOperations(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { branchID := c.Params("id") id, err := strconv.ParseInt(branchID, 10, 64) if err != nil { logger.Error("Invalid branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil) } operations, err := branchSvc.GetBranchOperations(c.Context(), id) if err != nil { logger.Error("Failed to get operation by ID", "branchID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve operation", err, nil) } var result []BranchOperationRes = make([]BranchOperationRes, len(operations)) for _, branch := range operations { result = append(result, BranchOperationRes{ Name: branch.OperationName, Description: branch.OperationDescription, }) } return response.WriteJSON(c, fiber.StatusOK, "Branch Operations retrieved successfully", result, nil) } } func UpdateBranch(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { branchID := c.Params("id") id, err := strconv.ParseInt(branchID, 10, 64) if err != nil { logger.Error("Invalid branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil) } var req CreateBranchReq if err := c.BodyParser(&req); err != nil { logger.Error("CreateBetReq failed", "error", err) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Invalid request", }) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } branch, err := branchSvc.UpdateBranch(c.Context(), id, domain.CreateBranch{ Name: req.Name, Location: req.Location, WalletID: req.WalletID, BranchManagerID: req.BranchManagerID, CompanyID: req.CompanyID, IsSelfOwned: req.IsSelfOwned, }) if err != nil { logger.Error("Failed to update branch", "branchID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update branch", err, nil) } res := convertBranch(branch) return response.WriteJSON(c, fiber.StatusOK, "Branch Updated", res, nil) } } func DeleteBranch(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { branchID := c.Params("id") id, err := strconv.ParseInt(branchID, 10, 64) if err != nil { logger.Error("Invalid Branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Branch ID", err, nil) } err = branchSvc.DeleteBranch(c.Context(), id) if err != nil { logger.Error("Failed to delete by ID", "Branch ID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Branch", err, nil) } return response.WriteJSON(c, fiber.StatusOK, "Branch removed successfully", nil, nil) } } func DeleteBranchOperation(logger *slog.Logger, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { branchID := c.Params("id") opID := c.Params("opID") id, err := strconv.ParseInt(branchID, 10, 64) if err != nil { logger.Error("Invalid Branch ID", "branchID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Branch ID", err, nil) } operationID, err := strconv.ParseInt(opID, 10, 64) if err != nil { logger.Error("Invalid Operation ID", "operationID", opID, "error", err) return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Operation ID", err, nil) } err = branchSvc.DeleteBranchOperation(c.Context(), id, operationID) if err != nil { logger.Error("Failed to delete operation", "Branch ID", id, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to Delete Operation", err, nil) } return response.WriteJSON(c, fiber.StatusOK, "Branch Operation removed successfully", nil, nil) } }