package app

import (
	"github.com/break/junhong_cmp_fiber/internal/middleware"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	clientAuthSvc "github.com/break/junhong_cmp_fiber/internal/service/client_auth"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/logger"
	"github.com/break/junhong_cmp_fiber/pkg/response"
	"github.com/go-playground/validator/v10"
	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"
)

var clientAuthValidator = validator.New()

// ClientAuthHandler C 端认证处理器
type ClientAuthHandler struct {
	service *clientAuthSvc.Service
	logger  *zap.Logger
}

// NewClientAuthHandler 创建 C 端认证处理器
func NewClientAuthHandler(service *clientAuthSvc.Service, logger *zap.Logger) *ClientAuthHandler {
	return &ClientAuthHandler{service: service, logger: logger}
}

// VerifyAsset A1 资产验证
// POST /api/c/v1/auth/verify-asset
func (h *ClientAuthHandler) VerifyAsset(c *fiber.Ctx) error {
	var req dto.VerifyAssetRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := clientAuthValidator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("资产验证参数校验失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}

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

// WechatLogin A2 公众号登录
// POST /api/c/v1/auth/wechat-login
func (h *ClientAuthHandler) WechatLogin(c *fiber.Ctx) error {
	var req dto.WechatLoginRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := clientAuthValidator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("公众号登录参数校验失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}

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

// MiniappLogin A3 小程序登录
// POST /api/c/v1/auth/miniapp-login
func (h *ClientAuthHandler) MiniappLogin(c *fiber.Ctx) error {
	var req dto.MiniappLoginRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := clientAuthValidator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("小程序登录参数校验失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}

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

// SendCode A4 发送验证码
// POST /api/c/v1/auth/send-code
func (h *ClientAuthHandler) SendCode(c *fiber.Ctx) error {
	var req dto.ClientSendCodeRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := clientAuthValidator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("发送验证码参数校验失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}

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

// BindPhone A5 绑定手机号
// POST /api/c/v1/auth/bind-phone
func (h *ClientAuthHandler) BindPhone(c *fiber.Ctx) error {
	customerID, ok := middleware.GetCustomerID(c)
	if !ok || customerID == 0 {
		return errors.New(errors.CodeUnauthorized)
	}

	var req dto.BindPhoneRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := clientAuthValidator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("绑定手机号参数校验失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}

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

// ChangePhone A6 更换手机号
// POST /api/c/v1/auth/change-phone
func (h *ClientAuthHandler) ChangePhone(c *fiber.Ctx) error {
	customerID, ok := middleware.GetCustomerID(c)
	if !ok || customerID == 0 {
		return errors.New(errors.CodeUnauthorized)
	}

	var req dto.ChangePhoneRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := clientAuthValidator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("更换手机号参数校验失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}

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

// DevLogin 开发环境测试登录（仅开发模式可用）
// POST /api/c/v1/auth/dev-login
func (h *ClientAuthHandler) DevLogin(c *fiber.Ctx) error {
	var req dto.DevLoginRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam)
	}
	if err := clientAuthValidator.Struct(&req); err != nil {
		h.logger.Warn("测试登录参数校验失败", zap.Error(err))
		return errors.New(errors.CodeInvalidParam)
	}

	token, customerID, isNewUser, err := h.service.DevLogin(c.UserContext(), req.Identifier)
	if err != nil {
		return err
	}
	return response.Success(c, dto.DevLoginResponse{
		Token:      token,
		CustomerID: customerID,
		IsNewUser:  isNewUser,
	})
}

// Logout A7 退出登录
// POST /api/c/v1/auth/logout
func (h *ClientAuthHandler) Logout(c *fiber.Ctx) error {
	customerID, ok := middleware.GetCustomerID(c)
	if !ok || customerID == 0 {
		return errors.New(errors.CodeUnauthorized)
	}

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