package User

import (
	"context"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/suyuan32/simple-admin-common/msg/errormsg"
	"github.com/zeromicro/go-zero/core/errorx"
	"time"
	"wechat-api/ent"
	"wechat-api/ent/wxcarduser"
	"wechat-api/hook/wechat"
	"wechat-api/internal/svc"
	"wechat-api/internal/types"
	"wechat-api/internal/utils/dberrorhandler"
	"wechat-api/internal/utils/jwt"

	"github.com/zeromicro/go-zero/core/logx"
)

type DoApiUserLoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewDoApiUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DoApiUserLoginLogic {
	return &DoApiUserLoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx}
}

func (l *DoApiUserLoginLogic) DoApiUserLogin(req *types.UserLoginReq) (*types.UserLoginResp, error) {
	var err error

	AppId := l.svcCtx.Config.Miniprogram.Appid
	Secret := l.svcCtx.Config.Miniprogram.Secret

	// 1. 初始化小程序应用实例
	app, err := wechat.NewClient(AppId, Secret)
	if err != nil {
		return nil, errorx.NewApiInternalError("init wechat miniprogram failed")
	}

	// 2. 调用小程序的授权登陆接口
	code := *req.JsCode // 前端小程序登录时，从微信获取的code
	resp, err := app.Auth.Session(code)

	if err != nil {
		return nil, errorx.NewApiInternalError("wechat login error")
	}

	if resp.OpenID == "" {
		return nil, errorx.NewApiInternalError(resp.ErrMSG)
	}

	userInfo, err := l.svcCtx.DB.WxCardUser.Query().Where(wxcarduser.OpenID(resp.OpenID)).First(l.ctx)
	if err != nil {
		if ent.IsNotFound(err) {
			userInfo, err = l.svcCtx.DB.WxCardUser.Create().
				SetOpenID(resp.OpenID).
				SetUnionID(resp.UnionID).
				SetSessionKey(resp.SessionKey).
				Save(l.ctx)
			if err != nil {
				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
			}
		} else {
			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
		}
	} else {
		_, err = l.svcCtx.DB.WxCardUser.Update().Where(wxcarduser.OpenID(resp.OpenID)).SetSessionKey(resp.SessionKey).Save(l.ctx)
		if err != nil {
			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
		}
	}

	// 这里需要改成实际用户的数据
	dataArray := make([]jwt.Option, 0)
	dataArray = append(dataArray, jwt.Option{
		Key: "userId",
		Val: userInfo.ID,
	})
	token, err := jwt.NewJwtToken(
		l.svcCtx.Config.Auth.AccessSecret,
		time.Now().Unix(),
		86400*30,
		dataArray...,
	)
	if err != nil {
		return nil, errorx.NewInvalidArgumentError(err.Error())
	}

	return &types.UserLoginResp{
		BaseDataInfo: types.BaseDataInfo{
			Code: 0,
			Msg:  errormsg.Success,
		},
		Data: types.UserToken{
			ID:       &userInfo.ID,
			Token:    &token,
			Avatar:   &userInfo.Avatar,
			Nickname: &userInfo.Nickname,
			IsVip:    tea.Bool(userInfo.IsVip > 0),
		},
	}, nil
}
