package admin

import (
	"strconv"

	"github.com/go-playground/validator/v10"
	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"

	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/logger"
	"github.com/break/junhong_cmp_fiber/pkg/response"

	roleApp "github.com/break/junhong_cmp_fiber/internal/application/role"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	roleService "github.com/break/junhong_cmp_fiber/internal/service/role"
)

// RoleHandler 角色 Handler
type RoleHandler struct {
	service              *roleService.Service
	defaultCreditService *roleApp.DefaultCreditService
	validator            *validator.Validate
}

// SetDefaultCreditService 设置角色默认信用模板应用服务。
func (h *RoleHandler) SetDefaultCreditService(service *roleApp.DefaultCreditService) {
	h.defaultCreditService = service
}

// NewRoleHandler 创建角色 Handler
func NewRoleHandler(service *roleService.Service, validator *validator.Validate) *RoleHandler {
	return &RoleHandler{
		service:   service,
		validator: validator,
	}
}

// Create 创建角色
// POST /api/admin/roles
func (h *RoleHandler) Create(c *fiber.Ctx) error {
	var req dto.CreateRoleRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	role, err := h.service.Create(c.UserContext(), &req)
	if err != nil {
		return err
	}

	return response.Success(c, role)
}

// Get 获取角色详情
// GET /api/admin/roles/:id
func (h *RoleHandler) Get(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	role, err := h.service.Get(c.UserContext(), uint(id))
	if err != nil {
		return err
	}

	return response.Success(c, role)
}

// Update 更新角色
// PUT /api/admin/roles/:id
func (h *RoleHandler) Update(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	var req dto.UpdateRoleRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	role, err := h.service.Update(c.UserContext(), uint(id), &req)
	if err != nil {
		return err
	}

	return response.Success(c, role)
}

// Delete 删除角色
// DELETE /api/admin/roles/:id
func (h *RoleHandler) Delete(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	if err := h.service.Delete(c.UserContext(), uint(id)); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// List 查询角色列表
// GET /api/admin/roles
func (h *RoleHandler) List(c *fiber.Ctx) error {
	var req dto.RoleListRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	roles, total, err := h.service.List(c.UserContext(), &req)
	if err != nil {
		return err
	}

	return response.SuccessWithPagination(c, roles, total, req.Page, req.PageSize)
}

// AssignPermissions 为角色分配权限
// POST /api/admin/roles/:id/permissions
func (h *RoleHandler) AssignPermissions(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	var req dto.AssignPermissionsRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	rps, err := h.service.AssignPermissions(c.UserContext(), uint(id), req.PermIDs)
	if err != nil {
		return err
	}

	return response.Success(c, rps)
}

// GetPermissions 获取角色的所有权限
// GET /api/admin/roles/:id/permissions
func (h *RoleHandler) GetPermissions(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	permissions, err := h.service.GetPermissions(c.UserContext(), uint(id))
	if err != nil {
		return err
	}

	return response.Success(c, permissions)
}

// RemovePermission 移除角色的权限
// DELETE /api/admin/roles/:role_id/permissions/:perm_id
func (h *RoleHandler) RemovePermission(c *fiber.Ctx) error {
	roleID, err := strconv.ParseUint(c.Params("role_id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	permID, err := strconv.ParseUint(c.Params("perm_id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的权限 ID")
	}

	if err := h.service.RemovePermission(c.UserContext(), uint(roleID), uint(permID)); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// BatchRemovePermissions 批量移除角色的权限
// DELETE /api/admin/roles/:role_id/permissions
func (h *RoleHandler) BatchRemovePermissions(c *fiber.Ctx) error {
	roleID, err := strconv.ParseUint(c.Params("role_id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	var req dto.BatchRemovePermissionsRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	if err := h.service.BatchRemovePermissions(c.UserContext(), uint(roleID), req.PermIDs); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// UpdateStatus 更新角色状态
// PUT /api/admin/roles/:id/status
func (h *RoleHandler) UpdateStatus(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	var req dto.UpdateRoleStatusRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	if err := h.service.UpdateStatus(c.UserContext(), uint(id), *req.Status); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// UpdateDefaultCredit 更新客户角色的新建代理默认信用模板。
// PUT /api/admin/roles/:id/default-credit
func (h *RoleHandler) UpdateDefaultCredit(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 64)
	if err != nil || id == 0 {
		return errors.New(errors.CodeInvalidParam, "无效的角色 ID")
	}

	var req dto.UpdateRoleDefaultCreditRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("角色默认信用参数验证失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}
	if h.defaultCreditService == nil {
		return errors.New(errors.CodeInternalError, "角色默认信用服务未配置")
	}

	role, err := h.defaultCreditService.Update(c.UserContext(), uint(id), *req.CreditEnabled, *req.CreditLimit)
	if err != nil {
		return err
	}
	return response.Success(c, dto.RoleDefaultCreditResponse{
		RoleID:                 role.ID,
		CreditEnabled:          role.DefaultCreditEnabled,
		CreditLimit:            role.DefaultCreditLimit,
		Scope:                  "new_shops_only",
		AffectsExistingWallets: false,
	})
}
