package app

import (
	"net/http"
	"time"

	"bindbox-game/configs"
	"bindbox-game/internal/code"
	"bindbox-game/internal/pkg/core"
	"bindbox-game/internal/pkg/jwtoken"
	"bindbox-game/internal/pkg/validation"
	"bindbox-game/internal/proposal"
	usersvc "bindbox-game/internal/service/user"

	"go.uber.org/zap"
)

// ============================================
// 发送短信验证码
// ============================================

type sendSmsCodeRequest struct {
	Mobile string `json:"mobile" binding:"required"`
}

type sendSmsCodeResponse struct {
	Success       bool `json:"success"`
	ExpireSeconds int  `json:"expire_seconds"`
}

// SendSmsCode 发送短信验证码
// @Summary 发送短信验证码
// @Description 发送短信验证码到指定手机号（60秒内不可重复发送，每日最多10次）
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Param RequestBody body sendSmsCodeRequest true "请求参数"
// @Success 200 {object} sendSmsCodeResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/sms/send-code [post]
func (h *handler) SendSmsCode() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(sendSmsCodeRequest)
		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		if err := h.user.SendSmsCode(ctx.RequestContext(), req.Mobile); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, err.Error()))
			return
		}

		ctx.Payload(&sendSmsCodeResponse{
			Success:       true,
			ExpireSeconds: 300, // 5分钟有效期
		})
	}
}

// ============================================
// 短信验证码登录
// ============================================

type smsLoginRequest struct {
	Mobile     string `json:"mobile" binding:"required"`
	Code       string `json:"code" binding:"required"`
	InviteCode string `json:"invite_code"`
}

type smsLoginResponse struct {
	UserID     int64  `json:"user_id"`
	Nickname   string `json:"nickname"`
	Avatar     string `json:"avatar"`
	InviteCode string `json:"invite_code"`
	Mobile     string `json:"mobile"`
	Token      string `json:"token"`
	OpenID     string `json:"openid"`
	IsNewUser  bool   `json:"is_new_user"`
}

// SmsLogin 短信验证码登录
// @Summary 短信验证码登录
// @Description 使用短信验证码登录或注册（新手机号自动创建账户）
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Param RequestBody body smsLoginRequest true "请求参数"
// @Success 200 {object} smsLoginResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/sms/login [post]
func (h *handler) SmsLogin() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(smsLoginRequest)
		rsp := new(smsLoginResponse)

		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		in := usersvc.SmsLoginInput{
			Mobile:     req.Mobile,
			Code:       req.Code,
			InviteCode: req.InviteCode,
		}

		out, err := h.user.LoginByCode(ctx.RequestContext(), in)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, err.Error()))
			return
		}

		u := out.User
		rsp.UserID = u.ID
		rsp.Nickname = u.Nickname
		rsp.Avatar = u.Avatar
		rsp.InviteCode = u.InviteCode
		rsp.Mobile = u.Mobile
		rsp.OpenID = u.Openid
		rsp.IsNewUser = out.IsNewUser

		// 触发邀请奖励逻辑
		if out.IsNewUser && out.InviterID > 0 {
			if err := h.task.OnInviteSuccess(ctx.RequestContext(), out.InviterID, u.ID); err != nil {
				h.logger.Error("触发邀请任务失败", zap.Error(err), zap.Int64("inviter_id", out.InviterID), zap.Int64("invitee_id", u.ID))
			}
		}

		h.logger.Info("短信登录返回数据",
			zap.Int64("user_id", u.ID),
			zap.String("mobile", u.Mobile),
			zap.String("openid", u.Openid),
			zap.Bool("is_new", out.IsNewUser),
		)

		// 签发JWT Token
		sessionUserInfo := proposal.SessionUserInfo{
			Id:       int32(u.ID),
			UserName: u.Nickname,
			NickName: u.Nickname,
			IsSuper:  0,
			Platform: "APP",
		}
		tokenString, tErr := jwtoken.New(configs.Get().JWT.PatientSecret).Sign(sessionUserInfo, 30*24*time.Hour)
		if tErr == nil {
			rsp.Token = tokenString
		}

		ctx.Payload(rsp)
	}
}
