package authsrv

import (
	"Cold_Logistic/internal/pkg/common/codex"
	"Cold_Logistic/internal/pkg/common/constant"
	"Cold_Logistic/internal/pkg/common/global"
	"Cold_Logistic/internal/server/domain/domainservice"
	"Cold_Logistic/internal/server/infra/dao"
	"Cold_Logistic/internal/server/infra/models"
	"Cold_Logistic/internal/server/infra/thirdparty/internalservice/clod"
	"context"
	"fmt"
	"gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/errors"
	"gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/util/authutil"
	"time"
)

type AuthService struct {
	store *dao.DataStore
}

func NewAuthService(store *dao.DataStore) *AuthService {
	return &AuthService{store: store}
}

const limitTime = 7 * 24 * time.Hour

// UserLogin 普通用户登录
func (srv *AuthService) UserLogin(ctx context.Context, req LoginReqVo) (res LoginRespVo, err error) {
	token := ""
	exp := time.Now().Add(limitTime).Unix()
	account := models.Account{}
	err = srv.store.InTx(ctx, func(tx context.Context) error {
		account, err = srv.store.Account().FindByOpenid(tx, req.Openid, req.LoginType)
		if err != nil {
			return errors.WithStackOnce(err)
		}
		if account.Id == 0 {
			account.Openid = req.Openid
			account.AccountType = req.LoginType
			account.FirstLogin = constant.YES
			if err = srv.store.Account().Create(tx, &account); err != nil {
				return errors.WithStackOnce(err)
			}
		}

		// 签发token
		token = authutil.Sign(account.Id, "", constant.CCLAppletLoginJWTISS, "", exp)
		if _, err = domainservice.SetTokenAndInfo(ctx, account, token, limitTime); err != nil {
			return errors.WithStackOnce(err)
		}
		return nil
	})
	if err != nil {
		return res, errors.WithStackOnce(err)
	}
	res.AccessToken = token
	res.TokenType = constant.AuthTokenTypeBearer
	res.ExpiresIn = exp
	res.IsFirst = account.FirstLogin
	return res, nil
}

// PlatformLogin 平台账号登录
func (srv *AuthService) PlatformLogin(ctx context.Context, req LoginReqVo) (res LoginRespVo, err error) {
	ok, pid, user, err := clod.NewBzdClodService().LoginVerification(ctx, req.TokenKey)
	if !ok || err != nil {
		return res, errors.WithCode(codex.ErrSignatureInvalid, "验证失败,请重新登陆")
	}

	token := ""
	exp := time.Now().Add(limitTime).Unix()
	account := models.Account{}
	err = srv.store.InTx(ctx, func(tx context.Context) error {
		account, err = srv.store.Account().FindByUuid(ctx, user.T_uuid)
		if err != nil {
			return errors.WithStackOnce(err)
		}

		account.Name = user.T_name
		account.Phone = user.T_phone
		account.PowerId = user.T_power
		account.UsePid = user.T_pid
		if pid > 0 {
			account.UsePid = pid
		}

		if account.Id == 0 {
			account.Uuid = user.T_uuid
			account.AccountType = constant.AccountPlatform
			account.FirstLogin = constant.NO
			account.Pid = user.T_pid
			if err = srv.store.Account().Create(ctx, &account); err != nil {
				return errors.WithStackOnce(err)
			}
		}

		if err = srv.store.Account().UpdateById(tx, &account); err != nil {
			return errors.WithStackOnce(err)
		}

		// 签发token
		token = authutil.Sign(account.Id, "", constant.CCLAppletLoginJWTISS, "", exp)
		if _, err = domainservice.SetTokenAndInfo(ctx, account, token, limitTime); err != nil {
			return errors.WithStackOnce(err)
		}

		return nil
	})
	if err != nil {
		return res, errors.WithStackOnce(err)
	}

	res.AccessToken = token
	res.TokenType = constant.AuthTokenTypeBearer
	res.ExpiresIn = exp
	return res, nil
}

func (srv *AuthService) LoginOut(ctx context.Context) error {
	tokenInfo := global.GetTokenInfoFromContext(ctx)
	_, err := global.CommonConnectRepoInst.Redis.
		HDel(ctx, fmt.Sprintf("acc_%d", tokenInfo.AccountId)).Result()
	return errors.WithStackOnce(err)
}