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 douyinLoginRequest struct {
	Code          string `json:"code"`
	AnonymousCode string `json:"anonymous_code"`
	InviteCode    string `json:"invite_code"`
	ChannelCode   string `json:"channel_code"`
}

type douyinLoginResponse struct {
	UserID     int64  `json:"user_id"`
	Nickname   string `json:"nickname"`
	Avatar     string `json:"avatar"`
	Mobile     string `json:"mobile"` // 新增手机号字段
	InviteCode string `json:"invite_code"`
	Token      string `json:"token"`
}

// DouyinLogin 抖音登录
// @Summary 抖音登录
// @Description 抖音小程序登录（需传递 code 或 anonymous_code）
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Param RequestBody body douyinLoginRequest true "请求参数"
// @Success 200 {object} douyinLoginResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/users/douyin/login [post]
func (h *handler) DouyinLogin() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(douyinLoginRequest)
		rsp := new(douyinLoginResponse)
		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		if req.Code == "" && req.AnonymousCode == "" {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "code 或 anonymous_code 不能为空"))
			return
		}

		in := usersvc.LoginDouyinInput{
			Code:          req.Code,
			AnonymousCode: req.AnonymousCode,
			InviteCode:    req.InviteCode,
			ChannelCode:   req.ChannelCode,
		}
		out, err := h.user.LoginDouyin(ctx.RequestContext(), in)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, 10006, err.Error()))
			return
		}

		u := out.User
		rsp.UserID = u.ID
		rsp.Nickname = u.Nickname
		rsp.Avatar = u.Avatar
		rsp.Mobile = u.Mobile // 返回手机号
		rsp.InviteCode = u.InviteCode

		// 触发邀请奖励逻辑
		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))
			}
		}

		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)
	}
}
