package openapi

import (
	"github.com/go-playground/validator/v10"
	"github.com/gofiber/fiber/v2"

	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	agentOpenAPIService "github.com/break/junhong_cmp_fiber/internal/service/agent_open_api"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/response"
)

// Handler 代理开放接口处理器
type Handler struct {
	service   *agentOpenAPIService.Service
	validator *validator.Validate
}

// NewHandler 创建代理开放接口处理器
func NewHandler(service *agentOpenAPIService.Service, validator *validator.Validate) *Handler {
	return &Handler{
		service:   service,
		validator: validator,
	}
}

// GetCardTraffic 查询单卡流量
// GET /api/open/v1/cards/traffic
func (h *Handler) GetCardTraffic(c *fiber.Ctx) error {
	var req dto.AgentOpenAPICardQueryRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	resp, err := h.service.GetCardTraffic(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.Success(c, resp)
}

// GetCardStatus 查询单卡状态
// GET /api/open/v1/cards/status
func (h *Handler) GetCardStatus(c *fiber.Ctx) error {
	var req dto.AgentOpenAPICardQueryRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	resp, err := h.service.GetCardStatus(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.Success(c, resp)
}

// GetRealnameStatus 查询单卡实名状态
// GET /api/open/v1/cards/realname-status
func (h *Handler) GetRealnameStatus(c *fiber.Ctx) error {
	var req dto.AgentOpenAPICardQueryRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	resp, err := h.service.GetRealnameStatus(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.Success(c, resp)
}

// ResumeCard 机卡分离卡复机
// POST /api/open/v1/cards/resume
func (h *Handler) ResumeCard(c *fiber.Ctx) error {
	var req dto.AgentOpenAPICardResumeRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	resp, err := h.service.ResumeCard(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.Success(c, resp)
}

// ListPackages 查询代理可购买套餐列表
// GET /api/open/v1/packages
func (h *Handler) ListPackages(c *fiber.Ctx) error {
	var req dto.AgentOpenAPIPackageListRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	items, total, page, pageSize, err := h.service.ListPackages(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.SuccessWithPagination(c, items, total, page, pageSize)
}

// CreateWalletPackageOrders 使用预充值钱包购买套餐
// POST /api/open/v1/wallet/package-orders
func (h *Handler) CreateWalletPackageOrders(c *fiber.Ctx) error {
	var req dto.AgentOpenAPIWalletPackageOrderRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	resp, err := h.service.CreateWalletPackageOrders(c.UserContext(), &req)
	if err != nil {
		return err
	}
	if resp.FailedCount > 0 {
		failure := resp.FailedCards[0]
		return response.Business(c, failure.Code, resp, failure.Message)
	}
	return response.Success(c, resp)
}

// GetWalletBalance 查询预充值钱包余额
// GET /api/open/v1/wallet/balance
func (h *Handler) GetWalletBalance(c *fiber.Ctx) error {
	resp, err := h.service.GetWalletBalance(c.UserContext())
	if err != nil {
		return err
	}
	return response.Success(c, resp)
}

// ListWalletTransactions 查询预充值钱包流水
// GET /api/open/v1/wallet/transactions
func (h *Handler) ListWalletTransactions(c *fiber.Ctx) error {
	var req dto.AgentOpenAPIWalletTransactionListRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	result, err := h.service.ListWalletTransactions(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.SuccessWithPagination(c, result.Items, result.Total, result.Page, result.Size)
}

// GetDeviceTraffic 查询设备套餐内流量
// GET /api/open/v1/devices/traffic
func (h *Handler) GetDeviceTraffic(c *fiber.Ctx) error {
	var req dto.AgentOpenAPIDeviceQueryRequest
	if err := c.QueryParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

	resp, err := h.service.GetDeviceTraffic(c.UserContext(), &req)
	if err != nil {
		return err
	}
	return response.Success(c, resp)
}

// SwitchDeviceCard 切网（多卡设备切换到指定 ICCID）
// POST /api/open/v1/devices/switch-card
func (h *Handler) SwitchDeviceCard(c *fiber.Ctx) error {
	var req dto.AgentOpenAPIDeviceSwitchCardRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

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

// RebootDevice 重启设备
// POST /api/open/v1/devices/reboot
func (h *Handler) RebootDevice(c *fiber.Ctx) error {
	var req dto.AgentOpenAPIDeviceOperationRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

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

// ResetDevice 恢复出厂设置
// POST /api/open/v1/devices/reset
func (h *Handler) ResetDevice(c *fiber.Ctx) error {
	var req dto.AgentOpenAPIDeviceOperationRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := h.validate(&req); err != nil {
		return err
	}

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

func (h *Handler) validate(req any) error {
	if h.validator == nil {
		return nil
	}
	if err := h.validator.Struct(req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	return nil
}
