package admin

import (
	"github.com/gofiber/fiber/v2"

	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	deviceService "github.com/break/junhong_cmp_fiber/internal/service/device"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"github.com/break/junhong_cmp_fiber/pkg/response"
)

type DeviceHandler struct {
	service *deviceService.Service
}

func NewDeviceHandler(service *deviceService.Service) *DeviceHandler {
	return &DeviceHandler{
		service: service,
	}
}

func (h *DeviceHandler) List(c *fiber.Ctx) error {
	var req dto.ListDeviceRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

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

	return response.SuccessWithPagination(c, result.List, result.Total, result.Page, result.PageSize)
}

// BatchUpdateRealnamePolicy 批量更新设备实名认证策略。
// POST /api/admin/devices/batch-update-realname-policy
func (h *DeviceHandler) BatchUpdateRealnamePolicy(c *fiber.Ctx) error {
	var req dto.BatchUpdateAssetRealnamePolicyRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	result, err := h.service.BatchUpdateRealnamePolicy(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.Success(c, result)
}

func (h *DeviceHandler) Delete(c *fiber.Ctx) error {
	userType := middleware.GetUserTypeFromContext(c.UserContext())
	if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
		return errors.New(errors.CodeForbidden, "仅平台用户可删除设备")
	}

	virtualNo := c.Params("virtual_no")
	if virtualNo == "" {
		return errors.New(errors.CodeInvalidParam, "虚拟号不能为空")
	}

	device, err := h.service.GetByVirtualNo(c.UserContext(), virtualNo)
	if err != nil {
		return err
	}

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

	return response.Success(c, nil)
}

func (h *DeviceHandler) ListCards(c *fiber.Ctx) error {
	virtualNo := c.Params("virtual_no")
	if virtualNo == "" {
		return errors.New(errors.CodeInvalidParam, "虚拟号不能为空")
	}

	device, err := h.service.GetByVirtualNo(c.UserContext(), virtualNo)
	if err != nil {
		return err
	}

	result, err := h.service.ListBindings(c.UserContext(), device.ID)
	if err != nil {
		return err
	}

	return response.Success(c, result)
}

func (h *DeviceHandler) BindCard(c *fiber.Ctx) error {
	userType := middleware.GetUserTypeFromContext(c.UserContext())
	if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
		return errors.New(errors.CodeForbidden, "仅平台用户可绑定卡到设备")
	}

	virtualNo := c.Params("virtual_no")
	if virtualNo == "" {
		return errors.New(errors.CodeInvalidParam, "虚拟号不能为空")
	}

	device, err := h.service.GetByVirtualNo(c.UserContext(), virtualNo)
	if err != nil {
		return err
	}

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

	result, err := h.service.BindCard(c.UserContext(), device.ID, &req)
	if err != nil {
		return err
	}

	return response.Success(c, result)
}

func (h *DeviceHandler) UnbindCard(c *fiber.Ctx) error {
	userType := middleware.GetUserTypeFromContext(c.UserContext())
	if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
		return errors.New(errors.CodeForbidden, "仅平台用户可解绑设备的卡")
	}

	virtualNo := c.Params("virtual_no")
	if virtualNo == "" {
		return errors.New(errors.CodeInvalidParam, "虚拟号不能为空")
	}

	device, err := h.service.GetByVirtualNo(c.UserContext(), virtualNo)
	if err != nil {
		return err
	}

	iccid := c.Params("iccid")
	if iccid == "" {
		return errors.New(errors.CodeInvalidParam, "ICCID 不能为空")
	}

	card, cardErr := h.service.GetCardByICCID(c.UserContext(), iccid)
	if cardErr != nil {
		return cardErr
	}

	result, err := h.service.UnbindCard(c.UserContext(), device.ID, card.ID)
	if err != nil {
		return err
	}

	return response.Success(c, result)
}

func (h *DeviceHandler) Allocate(c *fiber.Ctx) error {
	var req dto.AllocateDevicesRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	userID := middleware.GetUserIDFromContext(c.UserContext())
	shopID := middleware.GetShopIDFromContext(c.UserContext())

	var shopIDPtr *uint
	if shopID > 0 {
		shopIDPtr = &shopID
	}

	result, err := h.service.AllocateDevices(c.UserContext(), &req, userID, shopIDPtr)
	if err != nil {
		return err
	}

	return response.Success(c, result)
}

func (h *DeviceHandler) Recall(c *fiber.Ctx) error {
	var req dto.RecallDevicesRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	userID := middleware.GetUserIDFromContext(c.UserContext())
	shopID := middleware.GetShopIDFromContext(c.UserContext())

	var shopIDPtr *uint
	if shopID > 0 {
		shopIDPtr = &shopID
	}

	result, err := h.service.RecallDevices(c.UserContext(), &req, userID, shopIDPtr)
	if err != nil {
		return err
	}

	return response.Success(c, result)
}

func (h *DeviceHandler) BatchSetSeriesBinding(c *fiber.Ctx) error {
	var req dto.BatchSetDeviceSeriesBindngRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	ctx := c.UserContext()
	userType := middleware.GetUserTypeFromContext(ctx)

	var operatorShopID *uint
	if userType == constants.UserTypeAgent {
		shopID := middleware.GetShopIDFromContext(ctx)
		if shopID > 0 {
			operatorShopID = &shopID
		}
	}

	result, err := h.service.BatchSetSeriesBinding(ctx, &req, operatorShopID)
	if err != nil {
		return err
	}

	return response.Success(c, result)
}

// GetGatewaySlots 查询设备卡槽信息
// GET /api/admin/devices/by-identifier/:identifier/gateway-slots
func (h *DeviceHandler) GetGatewaySlots(c *fiber.Ctx) error {
	identifier := c.Params("identifier")
	if identifier == "" {
		return errors.New(errors.CodeInvalidParam, "设备标识符不能为空")
	}

	resp, err := h.service.GatewayGetSlotInfo(c.UserContext(), identifier)
	if err != nil {
		return err
	}

	return response.Success(c, resp)
}

// SetWiFi 设置设备 WiFi
// PUT /api/admin/devices/by-identifier/:identifier/wifi
func (h *DeviceHandler) SetWiFi(c *fiber.Ctx) error {
	identifier := c.Params("identifier")
	if identifier == "" {
		return errors.New(errors.CodeInvalidParam, "设备标识符不能为空")
	}

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

	if err := h.service.GatewaySetWiFi(c.UserContext(), identifier, &req); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// SwitchCard 切换设备使用的卡
// POST /api/admin/devices/by-identifier/:identifier/switch-card
func (h *DeviceHandler) SwitchCard(c *fiber.Ctx) error {
	identifier := c.Params("identifier")
	if identifier == "" {
		return errors.New(errors.CodeInvalidParam, "设备标识符不能为空")
	}

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

	if err := h.service.GatewaySwitchCard(c.UserContext(), identifier, &req); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// SetSwitchMode 设置设备切卡模式
// POST /api/admin/devices/by-identifier/:identifier/switch-mode
func (h *DeviceHandler) SetSwitchMode(c *fiber.Ctx) error {
	identifier := c.Params("identifier")
	if identifier == "" {
		return errors.New(errors.CodeInvalidParam, "设备标识符不能为空")
	}

	var req dto.SetSwitchModeRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}
	if req.SwitchMode == nil {
		return errors.New(errors.CodeInvalidParam, "切卡模式不能为空")
	}
	if *req.SwitchMode != 0 && *req.SwitchMode != 1 {
		return errors.New(errors.CodeInvalidParam, "切卡模式仅支持0或1")
	}
	if req.IotCardID == 0 {
		return errors.New(errors.CodeInvalidParam, "目标卡资产ID不能为空")
	}

	if err := h.service.GatewaySwitchMode(c.UserContext(), identifier, &req); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// RebootDevice 重启设备
// POST /api/admin/devices/by-identifier/:identifier/reboot
func (h *DeviceHandler) RebootDevice(c *fiber.Ctx) error {
	identifier := c.Params("identifier")
	if identifier == "" {
		return errors.New(errors.CodeInvalidParam, "设备标识符不能为空")
	}

	if err := h.service.GatewayRebootDevice(c.UserContext(), identifier); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// ResetDevice 恢复设备出厂设置
// POST /api/admin/devices/by-identifier/:identifier/reset
func (h *DeviceHandler) ResetDevice(c *fiber.Ctx) error {
	identifier := c.Params("identifier")
	if identifier == "" {
		return errors.New(errors.CodeInvalidParam, "设备标识符不能为空")
	}

	if err := h.service.GatewayResetDevice(c.UserContext(), identifier); err != nil {
		return err
	}

	return response.Success(c, nil)
}
