package handlers

import (
	"strconv"
	"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 CreateManagerReq 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"`
}

// CreateManager godoc
// @Summary Create Manager
// @Description Create Manager
// @Tags manager
// @Accept json
// @Produce json
// @Param manger body CreateManagerReq true "Create manager"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /managers [post]
func (h *Handler) CreateManager(c *fiber.Ctx) error {

	// Get user_id from middleware

	var req CreateManagerReq
	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)
	}

	var companyID domain.ValidInt64
	role := c.Locals("role").(domain.Role)
	if role == domain.RoleSuperAdmin {
		if req.CompanyID == nil {
			h.logger.Error("RegisterUser failed error: company id is required")
			return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", "Company ID is required", nil)
		}
		companyID = domain.ValidInt64{
			Value: *req.CompanyID,
			Valid: true,
		}
	} else {
		companyID = c.Locals("company_id").(domain.ValidInt64)
	}

	user := domain.CreateUserReq{
		FirstName:   req.FirstName,
		LastName:    req.LastName,
		Email:       req.Email,
		PhoneNumber: req.PhoneNumber,
		Password:    req.Password,
		Role:        string(domain.RoleBranchManager),
		CompanyID:   companyID,
	}
	_, err := h.userSvc.CreateUser(c.Context(), user, true)
	if err != nil {
		h.logger.Error("CreateManager failed", "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to create manager", nil, nil)
	}
	return response.WriteJSON(c, fiber.StatusOK, "Manager created successfully", nil, nil)

}

type ManagersRes 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"`
}

// GetAllManagers godoc
// @Summary Get all Managers
// @Description Get all Managers
// @Tags manager
// @Accept json
// @Produce json
// @Param page query int false "Page number"
// @Param page_size query int false "Page size"
// @Success 200 {object} ManagersRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /managers [get]
func (h *Handler) GetAllManagers(c *fiber.Ctx) error {
	role := c.Locals("role").(domain.Role)
	companyId := c.Locals("company_id").(domain.ValidInt64)

	if role != domain.RoleSuperAdmin && !companyId.Valid {
		return fiber.NewError(fiber.StatusInternalServerError, "Cannot get company ID")
	}
	filter := user.Filter{
		Role:      string(domain.RoleBranchManager),
		CompanyID: companyId,
		Page: domain.ValidInt{
			Value: c.QueryInt("page", 1) - 1,
			Valid: true,
		},
		PageSize: domain.ValidInt{
			Value: c.QueryInt("page_size", 10),
			Valid: true,
		},
	}
	valErrs, ok := h.validator.Validate(c, filter)
	if !ok {
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
	}
	managers, total, err := h.userSvc.GetAllUsers(c.Context(), filter)
	if err != nil {
		h.logger.Error("GetAllManagers failed", "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get Managers", nil, nil)
	}

	var result []ManagersRes = make([]ManagersRes, len(managers))
	for index, manager := range managers {
		lastLogin, err := h.authSvc.GetLastLogin(c.Context(), manager.ID)
		if err != nil {
			if err == authentication.ErrRefreshTokenNotFound {
				lastLogin = &manager.CreatedAt
			} else {
				h.logger.Error("Failed to get user last login", "userID", manager.ID, "error", err)
				return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
			}
		}
		result[index] = ManagersRes{
			ID:            manager.ID,
			FirstName:     manager.FirstName,
			LastName:      manager.LastName,
			Email:         manager.Email,
			PhoneNumber:   manager.PhoneNumber,
			Role:          manager.Role,
			EmailVerified: manager.EmailVerified,
			PhoneVerified: manager.PhoneVerified,
			CreatedAt:     manager.CreatedAt,
			UpdatedAt:     manager.UpdatedAt,
			SuspendedAt:   manager.SuspendedAt,
			Suspended:     manager.Suspended,
			LastLogin:     *lastLogin,
		}
	}

	return response.WritePaginatedJSON(c, fiber.StatusOK, "Managers retrieved successfully", result, nil, filter.Page.Value, int(total))

}

// GetManagerByID godoc
// @Summary Get manager by id
// @Description Get a single manager by id
// @Tags manager
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} ManagersRes
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /managers/{id} [get]
func (h *Handler) GetManagerByID(c *fiber.Ctx) error {
	// branchId := int64(12) //c.Locals("branch_id").(int64)
	// filter := user.Filter{
	// 	Role: string(domain.RoleUser),
	// 	BranchId: user.ValidBranchId{
	// 		Value: branchId,
	// 		Valid: true,
	// 	},
	// 	Page:     c.QueryInt("page", 1),
	// 	PageSize: c.QueryInt("page_size", 10),
	// }
	// valErrs, ok := validator.Validate(c, filter)
	// if !ok {
	// 	return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
	// }

	userIDstr := c.Params("id")
	userID, err := strconv.ParseInt(userIDstr, 10, 64)
	if err != nil {
		h.logger.Error("failed to fetch user using UserID", "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid managers ID", nil, nil)
	}

	user, err := h.userSvc.GetUserByID(c.Context(), userID)
	if err != nil {
		h.logger.Error("Get User By ID failed", "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to get managers", nil, nil)
	}

	lastLogin, err := h.authSvc.GetLastLogin(c.Context(), user.ID)
	if err != nil {
		if err != authentication.ErrRefreshTokenNotFound {
			h.logger.Error("Failed to get user last login", "userID", user.ID, "error", err)
			return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve user last login")
		}

		lastLogin = &user.CreatedAt
	}

	res := ManagersRes{
		ID:            user.ID,
		FirstName:     user.FirstName,
		LastName:      user.LastName,
		Email:         user.Email,
		PhoneNumber:   user.PhoneNumber,
		Role:          user.Role,
		EmailVerified: user.EmailVerified,
		PhoneVerified: user.PhoneVerified,
		CreatedAt:     user.CreatedAt,
		UpdatedAt:     user.UpdatedAt,
		SuspendedAt:   user.SuspendedAt,
		Suspended:     user.Suspended,
		LastLogin:     *lastLogin,
	}

	return response.WriteJSON(c, fiber.StatusOK, "User retrieved successfully", res, nil)
}

type updateManagerReq struct {
	FirstName string `json:"first_name" example:"John"`
	LastName  string `json:"last_name" example:"Doe"`
	Suspended bool   `json:"suspended" example:"false"`
	CompanyID *int64 `json:"company_id,omitempty" example:"1"`
}

// UpdateManagers godoc
// @Summary Update Managers
// @Description Update Managers
// @Tags manager
// @Accept json
// @Produce json
// @Param Managers body updateManagerReq true "Update Managers"
// @Success 200 {object} response.APIResponse
// @Failure 400 {object} response.APIResponse
// @Failure 401 {object} response.APIResponse
// @Failure 500 {object} response.APIResponse
// @Router /managers/{id} [put]
func (h *Handler) UpdateManagers(c *fiber.Ctx) error {
	var req updateManagerReq
	if err := c.BodyParser(&req); err != nil {
		h.logger.Error("UpdateManagers failed", "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", nil, nil)
	}

	valErrs, ok := h.validator.Validate(c, req)

	if !ok {
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil)
	}
	ManagersIdStr := c.Params("id")
	ManagersId, err := strconv.ParseInt(ManagersIdStr, 10, 64)
	if err != nil {
		h.logger.Error("UpdateManagers failed", "error", err)
		return response.WriteJSON(c, fiber.StatusBadRequest, "Invalid Managers ID", nil, nil)
	}
	var companyID domain.ValidInt64
	role := c.Locals("role").(domain.Role)
	if req.CompanyID != nil {
		if role != domain.RoleSuperAdmin {
			h.logger.Error("UpdateManagers failed", "error", err)
			return response.WriteJSON(c, fiber.StatusUnauthorized, "This user role cannot modify company ID", nil, nil)
		}
		companyID = domain.ValidInt64{
			Value: *req.CompanyID,
			Valid: true,
		}
	}

	err = h.userSvc.UpdateUser(c.Context(), domain.UpdateUserReq{
		UserId: ManagersId,
		FirstName: domain.ValidString{
			Value: req.FirstName,
			Valid: req.FirstName != "",
		},
		LastName: domain.ValidString{
			Value: req.LastName,
			Valid: req.LastName != "",
		},
		Suspended: domain.ValidBool{
			Value: req.Suspended,
			Valid: true,
		},
		CompanyID: companyID,
	},
	)
	if err != nil {
		h.logger.Error("UpdateManagers failed", "error", err)
		return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to update Managers", nil, nil)
	}
	return response.WriteJSON(c, fiber.StatusOK, "Managers updated successfully", nil, nil)

}
