package handlers

import (
	"strconv"
	"strings"

	"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/services/authentication"
	"github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response"
	"github.com/gofiber/fiber/v2"
)

type CreateBranchReq struct {
	Name            string  `json:"name" validate:"required,min=3,max=100" example:"4-kilo Branch"`
	Location        string  `json:"location" validate:"required,min=3,max=100" example:"Addis Ababa"`
	BranchManagerID int64   `json:"branch_manager_id" validate:"required,gt=0" example:"1"`
	CompanyID       *int64  `json:"company_id,omitempty" example:"1"`
	IsSelfOwned     *bool   `json:"is_self_owned,omitempty" example:"false"`
	Operations      []int64 `json:"operations" validate:"required,dive,gt=0"`
}

type UpdateBranchReq struct {
	Name            *string `json:"name,omitempty" example:"4-kilo Branch"`
	Location        *string `json:"location,omitempty" example:"Addis Ababa"`
	BranchManagerID *int64  `json:"branch_manager_id,omitempty" example:"1"`
	CompanyID       *int64  `json:"company_id,omitempty" example:"1"`
	IsSelfOwned     *bool   `json:"is_self_owned,omitempty" 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 {
	ID              int64  `json:"id" example:"1"`
	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 {
	ID                 int64   `json:"id" example:"1"`
	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"`
	Balance            float32 `json:"balance" example:"100.5"`
}

func convertBranch(branch domain.Branch) BranchRes {
	return BranchRes{
		ID:              branch.ID,
		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{
		ID:                 branch.ID,
		Name:               branch.Name,
		Location:           branch.Location,
		WalletID:           branch.WalletID,
		BranchManagerID:    branch.BranchManagerID,
		CompanyID:          branch.CompanyID,
		IsSelfOwned:        branch.IsSelfOwned,
		ManagerName:        branch.ManagerName,
		ManagerPhoneNumber: branch.ManagerPhoneNumber,
		Balance:            branch.Balance.Float32(),
	}
}

// CreateBranch godoc
// @Summary Create a branch
// @Description Creates a branch
// @Tags branch
// @Accept json
// @Produce json
// @Param createBranch body CreateBranchReq true "Creates branch"
// @Success 200 {object} BranchRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch [post]
func (h *Handler) CreateBranch(c *fiber.Ctx) error {
	// Check if user is either branch manager / super main
	// role := string(c.Locals("role").(domain.Role))

	// if role != string(domain.RoleAdmin) && role != string(domain.RoleSuperAdmin) && role != string(domain.RoleBranchManager) {
	// 	logger.Error("Unauthorized access", "role", role)
	// 	return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
	// }

	role := c.Locals("role").(domain.Role)
	companyID := c.Locals("company_id").(domain.ValidInt64)

	var req CreateBranchReq

	if err := c.BodyParser(&req); err != nil {
		h.logger.Error("CreateBranchReq 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)
	}
	var IsSelfOwned bool
	var checkedCompanyID int64
	if role == domain.RoleSuperAdmin {
		if req.IsSelfOwned == nil {
			return response.WriteJSON(c, fiber.StatusBadRequest, "is_self_owned is required for super admin", nil, nil)
		}
		if req.CompanyID == nil {
			return response.WriteJSON(c, fiber.StatusBadRequest, "company_id is required for super admin", nil, nil)
		}
		IsSelfOwned = *req.IsSelfOwned
		checkedCompanyID = *req.CompanyID
	} else {
		IsSelfOwned = false
		checkedCompanyID = companyID.Value
		//TODO:check that the company id is always valid when its not a super admin
	}

	// Create Branch Wallet
	newWallet, err := h.walletSvc.CreateWallet(c.Context(), domain.CreateWallet{
		IsWithdraw:     false,
		IsBettable:     true,
		IsTransferable: true,
		UserID:         req.BranchManagerID,
	})

	if err != nil {
		h.logger.Error("Create Branch Wallet failed", "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create branch wallet", err, nil)
	}

	branch, err := h.branchSvc.CreateBranch(c.Context(), domain.CreateBranch{
		Name:            req.Name,
		Location:        req.Location,
		WalletID:        newWallet.ID,
		BranchManagerID: req.BranchManagerID,
		CompanyID:       checkedCompanyID,
		IsSelfOwned:     IsSelfOwned,
	})

	if err != nil {
		h.logger.Error("CreateBranchReq failed", "error", err)
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"error": "Internal server error",
		})
	}

	for _, operation := range req.Operations {
		err := h.branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
			BranchID:    branch.ID,
			OperationID: operation,
		})
		if err != nil {
			h.logger.Error("Failed to create branch operations", "BranchID", branch.ID, "operation", operation, "error", err)
			return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
				"error": "Internal server error",
			})
		}
	}

	res := convertBranch(branch)

	return response.WriteJSON(c, fiber.StatusCreated, "Branch Created", res, nil)
}

// CreateSupportedOperation godoc
// @Summary Create a supported operation
// @Description Creates a supported operation
// @Tags branch
// @Accept json
// @Produce json
// @Param createSupportedOperation body CreateSupportedOperationReq true "Creates supported operation"
// @Success 200 {object} SupportedOperationRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /supportedOperation [post]
func (h *Handler) CreateSupportedOperation(c *fiber.Ctx) error {
	var req CreateSupportedOperationReq

	if err := c.BodyParser(&req); err != nil {
		h.logger.Error("CreateSupportedOperationReq 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)
	}
	operation, err := h.branchSvc.CreateSupportedOperation(c.Context(), domain.CreateSupportedOperation{
		Name:        req.Name,
		Description: req.Description,
	})

	if err != nil {
		h.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)
}

// CreateBranchOperation godoc
// @Summary Create a operation
// @Description Creates a operation
// @Tags branch
// @Accept json
// @Produce json
// @Param createBranchOperation body CreateBranchOperationReq true "Creates operation"
// @Success 200 {object} BranchOperationRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /operation [post]
func (h *Handler) CreateBranchOperation(c *fiber.Ctx) error {
	var req CreateBranchOperationReq
	if err := c.BodyParser(&req); err != nil {
		h.logger.Error("CreateBranchOperationReq 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)
	}

	err := h.branchSvc.CreateBranchOperation(c.Context(), domain.CreateBranchOperation{
		BranchID:    req.BranchID,
		OperationID: req.OperationID,
	})

	if err != nil {
		h.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)
}

// GetBranchByID godoc
// @Summary Gets branch by id
// @Description Gets a single branch by id
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {object} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch/{id} [get]
func (h *Handler) GetBranchByID(c *fiber.Ctx) error {
	branchID := c.Params("id")
	id, err := strconv.ParseInt(branchID, 10, 64)
	if err != nil {
		h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
	}

	branch, err := h.branchSvc.GetBranchByID(c.Context(), id)

	if err != nil {
		h.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)
}

// GetBranchByManagerID godoc
// @Summary Gets branches by manager id
// @Description Gets a branches by manager id
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {array} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /manager/{id}/branch [get]
func (h *Handler) GetBranchByManagerID(c *fiber.Ctx) error {
	// TODO: Restrict any who isn't branch manager or higher
	userID := c.Params("id")
	id, err := strconv.ParseInt(userID, 10, 64)
	if err != nil {
		h.logger.Error("Invalid user ID", "userID", userID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid user ID", err, nil)
	}

	branches, err := h.branchSvc.GetBranchByManagerID(c.Context(), id)

	if err != nil {
		h.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, 0, len(branches))
	for _, branch := range branches {
		result = append(result, convertBranchDetail(branch))
	}
	return response.WriteJSON(c, fiber.StatusOK, "Branches for Branch Manager retrieved", result, nil)
}

// GetBranchByCompanyID godoc
// @Summary Gets branches by company id
// @Description Gets branches by company id
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Company ID"
// @Success 200 {array} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /company/{id}/branch [get]
func (h *Handler) GetBranchByCompanyID(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)
	}

	branches, err := h.branchSvc.GetBranchByCompanyID(c.Context(), id)
	if err != nil {
		h.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, 0, len(branches))
	for _, branch := range branches {
		result = append(result, convertBranchDetail(branch))
	}
	return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
}

// GetAllBranches godoc
// @Summary Gets all branches
// @Description Gets all branches
// @Tags branch
// @Accept json
// @Produce json
// @Success 200 {array} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch [get]
func (h *Handler) GetAllBranches(c *fiber.Ctx) error {
	// TODO: Limit the get all branches to only the companies for branch manager and cashiers
	branches, err := h.branchSvc.GetAllBranches(c.Context())
	if err != nil {
		h.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, 0, len(branches))
	for _, branch := range branches {
		result = append(result, convertBranchDetail(branch))
	}
	return response.WriteJSON(c, fiber.StatusOK, "Branches for Company retrieved", result, nil)
}

// SearchBranch godoc
// @Summary Search branches
// @Description Search branches by name or location
// @Tags branch
// @Accept json
// @Produce json
// @Param q query string true "Search query"
// @Success 200 {array} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /search/branch [get]
func (h *Handler) SearchBranch(c *fiber.Ctx) error {
	// Get search query from request
	searchQuery := c.Query("q")
	if searchQuery == "" {
		return response.WriteJSON(c, fiber.StatusBadRequest, "Search query is required", nil, nil)
	}

	// Call the service to search for branches
	branches, err := h.branchSvc.SearchBranchByName(c.Context(), searchQuery)
	if err != nil {
		h.logger.Error("Failed to search branches", "query", searchQuery, "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to search branches", err, nil)
	}

	// Convert branches to response format
	var result []BranchDetailRes
	for _, branch := range branches {
		result = append(result, convertBranchDetail(branch))
	}

	return response.WriteJSON(c, fiber.StatusOK, "Branches retrieved successfully", result, nil)
}

// GetAllSupportedOperations godoc
// @Summary Gets all supported operations
// @Description Gets all supported operations
// @Tags branch
// @Accept json
// @Produce json
// @Success 200 {array} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /supportedOperation [get]
func (h *Handler) GetAllSupportedOperations(c *fiber.Ctx) error {
	operations, err := h.branchSvc.GetAllSupportedOperations(c.Context())
	if err != nil {
		h.logger.Error("Failed to get operations", "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get operations", err, nil)
	}

	var result []SupportedOperationRes = make([]SupportedOperationRes, 0, len(operations))
	for _, operation := range operations {
		result = append(result, SupportedOperationRes{
			ID:          operation.ID,
			Name:        operation.Name,
			Description: operation.Description,
		})
	}
	return response.WriteJSON(c, fiber.StatusOK, "SupportedOperations for Company retrieved", result, nil)

}

// GetBranchOperations godoc
// @Summary Gets branch operations
// @Description Gets branch operations
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {array} BranchOperationRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch/{id}/operation [get]
func (h *Handler) GetBranchOperations(c *fiber.Ctx) error {
	branchID := c.Params("id")
	id, err := strconv.ParseInt(branchID, 10, 64)
	if err != nil {
		h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
	}

	operations, err := h.branchSvc.GetBranchOperations(c.Context(), id)

	if err != nil {
		h.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, 0, 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)
}

// GetBranchCashiers godoc
// @Summary Gets branch cashiers
// @Description Gets branch cashiers
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {array} GetCashierRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch/{id}/cashier [get]
func (h *Handler) GetBranchCashiers(c *fiber.Ctx) error {
	branchID := c.Params("id")
	id, err := strconv.ParseInt(branchID, 10, 64)
	if err != nil {
		h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
	}

	cashiers, err := h.userSvc.GetCashiersByBranch(c.Context(), id)

	if err != nil {
		h.logger.Error("Failed to get cashier by branch ID", "branchID", id, "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve cashier", err, nil)
	}

	var result []GetCashierRes = make([]GetCashierRes, 0, len(cashiers))

	for _, cashier := range cashiers {
		lastLogin, err := h.authSvc.GetLastLogin(c.Context(), cashier.ID)
		if err != nil {
			if err == authentication.ErrRefreshTokenNotFound {
				lastLogin = &cashier.CreatedAt
			} else {
				h.logger.Error("Failed to get user last login", "userID", cashier.ID, "error", err)
				return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
			}
		}
		result = append(result, GetCashierRes{
			ID:            cashier.ID,
			FirstName:     cashier.FirstName,
			LastName:      cashier.LastName,
			Email:         cashier.Email,
			PhoneNumber:   cashier.PhoneNumber,
			Role:          cashier.Role,
			EmailVerified: cashier.EmailVerified,
			PhoneVerified: cashier.PhoneVerified,
			CreatedAt:     cashier.CreatedAt,
			UpdatedAt:     cashier.UpdatedAt,
			SuspendedAt:   cashier.SuspendedAt,
			Suspended:     cashier.Suspended,
			LastLogin:     *lastLogin,
		})
	}

	return response.WriteJSON(c, fiber.StatusOK, "Branch Cashiers retrieved successfully", result, nil)
}

// GetBranchForCashier godoc
// @Summary Gets branch for cahier
// @Description Gets branch for cahier
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Success 200 {object} BranchDetailRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branchCashier [get]
func (h *Handler) GetBranchForCashier(c *fiber.Ctx) error {
	cashierID, ok := c.Locals("user_id").(int64)

	if !ok {
		h.logger.Error("Invalid cashier ID in context")
		return response.WriteJSON(c, fiber.StatusUnauthorized, "Invalid cashier identification", nil, nil)
	}

	role, ok := c.Locals("role").(domain.Role)

	if !ok || role != domain.RoleCashier {
		h.logger.Error("Unauthorized access", "cashierID", cashierID, "role", role)
		return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil)
	}

	branchID, ok := c.Locals("branch_id").(domain.ValidInt64)
	if !ok || !branchID.Valid {
		h.logger.Error("Invalid branch ID in context", "cashierID", cashierID)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", nil, nil)
	}

	branch, err := h.branchSvc.GetBranchByID(c.Context(), branchID.Value)

	if err != nil {
		h.logger.Error("Failed to get branch by ID", "branchID", branchID.Value, "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)
}

// GetBetByBranchID godoc
// @Summary Gets bets by its branch id
// @Description Gets bets by its branch id
// @Tags branch
// @Accept json
// @Produce json
// @Success 200 {array} domain.BetRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch/{id}/bets [get]
func (h *Handler) GetBetByBranchID(c *fiber.Ctx) error {
	branchID := c.Params("id")
	id, err := strconv.ParseInt(branchID, 10, 64)
	if err != nil {
		h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
	}

	bets, err := h.betSvc.GetBetByBranchID(c.Context(), id)

	if err != nil {
		h.logger.Error("Failed to get bets", "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve bets", err, nil)
	}

	var res []domain.BetRes = make([]domain.BetRes, 0, len(bets))
	for _, bet := range bets {
		res = append(res, domain.ConvertBet(bet))
	}

	return response.WriteJSON(c, fiber.StatusOK, "Branch Bets Retrieved", res, nil)
}

// UpdateBranch godoc
// @Summary Updates a branch
// @Description Updates a branch
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Param updateBranch body CreateBranchReq true "Update Branch"
// @Success 200 {object} BranchRes
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch/{id} [put]
func (h *Handler) UpdateBranch(c *fiber.Ctx) error {
	branchID := c.Params("id")
	id, err := strconv.ParseInt(branchID, 10, 64)
	if err != nil {
		h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
	}

	var req UpdateBranchReq

	if err := c.BodyParser(&req); err != nil {
		h.logger.Error("CreateBranchReq 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)
	}

	branch, err := h.branchSvc.UpdateBranch(c.Context(), domain.UpdateBranch{
		ID:              id,
		Name:            req.Name,
		Location:        req.Location,
		BranchManagerID: req.BranchManagerID,
		CompanyID:       req.CompanyID,
		IsSelfOwned:     req.IsSelfOwned,
	})

	if err != nil {
		h.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 (h *Handler) UpdateBranchStatus(c *fiber.Ctx) error {
	branchID := c.Params("id")
	id, err := strconv.ParseInt(branchID, 10, 64)
	if err != nil {
		h.logger.Error("Invalid branch ID", "branchID", branchID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch ID", err, nil)
	}

	var isActive bool
	path := strings.Split(strings.Trim(c.Path(), "/"), "/")

	if path[len(path)-1] == "set-active" {
		isActive = true
	} else if path[len(path)-1] == "set-inactive" {
		isActive = false
	} else {
		h.logger.Error("Invalid branch status", "status", isActive, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid branch status", err, nil)
	}

	branch, err := h.branchSvc.UpdateBranch(c.Context(), domain.UpdateBranch{
		ID:       id,
		IsActive: &isActive,
	})

	if err != nil {
		h.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)

}

// DeleteBranch godoc
// @Summary Delete the branch
// @Description Delete the branch
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID""
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch/{id} [delete]
func (h *Handler) DeleteBranch(c *fiber.Ctx) error {
	branchID := c.Params("id")
	id, err := strconv.ParseInt(branchID, 10, 64)

	if err != nil {
		h.logger.Error("Invalid Branch ID", "branchID", branchID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Branch ID", err, nil)
	}

	err = h.branchSvc.DeleteBranch(c.Context(), id)

	if err != nil {
		h.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)
}

// DeleteBranchOperation godoc
// @Summary Delete the branch operation
// @Description Delete the branch operation
// @Tags branch
// @Accept json
// @Produce json
// @Param id path int true "Branch ID"
// @Param opID path int true "Branch Operation ID"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /branch/{id}/operation/{opID} [delete]
func (h *Handler) DeleteBranchOperation(c *fiber.Ctx) error {
	branchID := c.Params("id")
	opID := c.Params("opID")

	id, err := strconv.ParseInt(branchID, 10, 64)

	if err != nil {
		h.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 {
		h.logger.Error("Invalid Operation ID", "operationID", opID, "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Operation ID", err, nil)
	}

	err = h.branchSvc.DeleteBranchOperation(c.Context(), id, operationID)

	if err != nil {
		h.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)

}
