// Package app 提供移动端（H5/小程序）的 HTTP 处理器
// 包含个人客户认证、注册、微信绑定等功能的 Handler 实现
package app

import (
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/service/personal_customer"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/response"
	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"
)

// PersonalCustomerHandler 个人客户处理器
type PersonalCustomerHandler struct {
	service *personal_customer.Service
	logger  *zap.Logger
}

// NewPersonalCustomerHandler 创建个人客户处理器实例
func NewPersonalCustomerHandler(service *personal_customer.Service, logger *zap.Logger) *PersonalCustomerHandler {
	return &PersonalCustomerHandler{
		service: service,
		logger:  logger,
	}
}

// SendCodeRequest 发送验证码请求
type SendCodeRequest struct {
	Phone string `json:"phone" validate:"required,len=11"` // 手机号（11位）
}

// SendCode 发送验证码
// POST /api/c/v1/login/send-code
func (h *PersonalCustomerHandler) SendCode(c *fiber.Ctx) error {
	var req SendCodeRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	// 发送验证码
	if err := h.service.SendVerificationCode(c.Context(), req.Phone); err != nil {
		h.logger.Error("发送验证码失败",
			zap.String("phone", req.Phone),
			zap.Error(err),
		)
		return errors.Wrap(errors.CodeInternalError, err, "发送验证码失败")
	}

	return response.Success(c, fiber.Map{
		"message": "验证码已发送",
	})
}

// LoginRequest 登录请求
type LoginRequest struct {
	Phone string `json:"phone" validate:"required,len=11"` // 手机号（11位）
	Code  string `json:"code" validate:"required,len=6"`   // 验证码（6位）
}

// LoginResponse 登录响应
type LoginResponse struct {
	Token    string               `json:"token"`    // 访问令牌
	Customer *PersonalCustomerDTO `json:"customer"` // 客户信息
}

// PersonalCustomerDTO 个人客户 DTO
type PersonalCustomerDTO struct {
	ID        uint   `json:"id"`
	Phone     string `json:"phone"`
	Nickname  string `json:"nickname"`
	AvatarURL string `json:"avatar_url"`
	WxOpenID  string `json:"wx_open_id"`
	Status    int    `json:"status"`
}

// Login 登录（手机号 + 验证码）
// POST /api/c/v1/login
func (h *PersonalCustomerHandler) Login(c *fiber.Ctx) error {
	var req LoginRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	// 登录
	token, customer, err := h.service.LoginByPhone(c.Context(), req.Phone, req.Code)
	if err != nil {
		h.logger.Error("登录失败",
			zap.String("phone", req.Phone),
			zap.Error(err),
		)
		return errors.Wrap(errors.CodeInternalError, err, "登录失败")
	}

	// 构造响应
	// 注意：Phone 字段已从 PersonalCustomer 模型移除，需要从 PersonalCustomerPhone 表查询
	resp := &LoginResponse{
		Token: token,
		Customer: &PersonalCustomerDTO{
			ID:        customer.ID,
			Phone:     req.Phone, // 使用请求中的手机号（临时方案）
			Nickname:  customer.Nickname,
			AvatarURL: customer.AvatarURL,
			WxOpenID:  customer.WxOpenID,
			Status:    customer.Status,
		},
	}

	return response.Success(c, resp)
}

// WechatOAuthLogin 微信 OAuth 登录
// POST /api/c/v1/wechat/auth
func (h *PersonalCustomerHandler) WechatOAuthLogin(c *fiber.Ctx) error {
	var req dto.WechatOAuthRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	result, err := h.service.WechatOAuthLogin(c.Context(), req.Code)
	if err != nil {
		h.logger.Error("微信 OAuth 登录失败",
			zap.String("code", req.Code),
			zap.Error(err),
		)
		return err
	}

	return response.Success(c, result)
}

// BindWechat 绑定微信
// POST /api/c/v1/bind-wechat
func (h *PersonalCustomerHandler) BindWechat(c *fiber.Ctx) error {
	var req dto.WechatOAuthRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	customerID, ok := c.Locals("customer_id").(uint)
	if !ok {
		return errors.New(errors.CodeUnauthorized, "未找到客户信息")
	}

	if err := h.service.BindWechatWithCode(c.Context(), customerID, req.Code); err != nil {
		h.logger.Error("绑定微信失败",
			zap.Uint("customer_id", customerID),
			zap.Error(err),
		)
		return err
	}

	return response.Success(c, fiber.Map{
		"message": "绑定成功",
	})
}

// UpdateProfileRequest 更新个人资料请求
type UpdateProfileRequest struct {
	Nickname  string `json:"nickname"`   // 昵称
	AvatarURL string `json:"avatar_url"` // 头像 URL
}

// UpdateProfile 更新个人资料
// PUT /api/c/v1/profile
func (h *PersonalCustomerHandler) UpdateProfile(c *fiber.Ctx) error {
	var req UpdateProfileRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	// 从 context 中获取当前登录的客户 ID
	customerID, ok := c.Locals("customer_id").(uint)
	if !ok {
		return errors.New(errors.CodeUnauthorized, "未找到客户信息")
	}

	if err := h.service.UpdateProfile(c.Context(), customerID, req.Nickname, req.AvatarURL); err != nil {
		h.logger.Error("更新个人资料失败",
			zap.Uint("customer_id", customerID),
			zap.Error(err),
		)
		return errors.Wrap(errors.CodeInternalError, err, "更新个人资料失败")
	}

	return response.Success(c, fiber.Map{
		"message": "更新成功",
	})
}

// GetProfile 获取个人资料
// GET /api/c/v1/profile
func (h *PersonalCustomerHandler) GetProfile(c *fiber.Ctx) error {
	// 从 context 中获取当前登录的客户 ID
	customerID, ok := c.Locals("customer_id").(uint)
	if !ok {
		return errors.New(errors.CodeUnauthorized, "未找到客户信息")
	}

	// 获取客户资料（包含主手机号）
	customer, phone, err := h.service.GetProfileWithPhone(c.Context(), customerID)
	if err != nil {
		h.logger.Error("获取个人资料失败",
			zap.Uint("customer_id", customerID),
			zap.Error(err),
		)
		return errors.Wrap(errors.CodeInternalError, err, "获取个人资料失败")
	}

	// 构造响应
	resp := &PersonalCustomerDTO{
		ID:        customer.ID,
		Phone:     phone, // 使用查询到的主手机号
		Nickname:  customer.Nickname,
		AvatarURL: customer.AvatarURL,
		WxOpenID:  customer.WxOpenID,
		Status:    customer.Status,
	}

	return response.Success(c, resp)
}
