package auth

import (
	"fmt"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/application/factory"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/domain"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/infrastructure/utils"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/log"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/protocol"
	"strings"
	"time"
)

func Login(header *protocol.RequestHeader, request *protocol.LoginRequest) (rsp *protocol.LoginResponse, err error) {
	var (
		transactionContext, _          = factory.CreateTransactionContext(nil)
		PartnerInfoService, _          = factory.CreatePartnerInfoRepositoryIn(transactionContext)
		partnerInfo                    *domain.PartnerInfo
		result                         bool = false
		PartnerSubAccountRepository, _      = factory.CreatePartnerSubAccountRepository(transactionContext)
		partnerSubAccount              *domain.PartnerSubAccount
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	rsp = &protocol.LoginResponse{}
	if partnerSubAccount, err = PartnerSubAccountRepository.FindOne(map[string]interface{}{"account": request.Phone}); err == nil {
		if partnerInfo, err = PartnerInfoService.FindOne(map[string]interface{}{"id": partnerSubAccount.PartnerId}); err != nil {
			//子账号
			err = protocol.NewErrWithMessage(502, err) //账号不存在
			return
		}
		partnerInfo.Password = partnerSubAccount.Password
	} else {
		if partnerInfo, err = PartnerInfoService.FindOne(map[string]interface{}{"account": request.Phone}); err != nil {
			//子账号
			err = protocol.NewErrWithMessage(502, err) //账号不存在
			return

		}
	}
	if !partnerInfo.IsEnable() {
		err = protocol.NewErrWithMessage(2002) //账号禁用
		return
	}
	switch request.GrantType {
	case protocol.LoginByPassword:
		if len(partnerInfo.Password) == 0 {
			err = protocol.NewCustomMessage(1, "密码不能为空!")
			return
		}
		if result = strings.EqualFold(partnerInfo.Password, request.Password); !result {
			err = protocol.NewCustomMessage(1, "密码输入有误!")
			return
		}
		break
	case protocol.LoginBySmsCode:
		if _, err = CheckSmsCode(request.Phone, request.Captcha); err != nil {
			return
		}
		break
	default:
		err = protocol.NewCustomMessage(1, "登录方式不支持!")
		break
	}
	rsp.AuthCode, _ = utils.GenerateToken(partnerInfo.Id, protocol.AuthCodeExpire*time.Second)

	if err = InitOrUpdateUserIMInfo(partnerInfo, transactionContext); err != nil {
		log.Error(err)
		return
	}
	err = transactionContext.CommitTransaction()
	return
}

func SmsCode(request *protocol.SmsCodeRequest) (rsp *protocol.SmsCodeResponse, err error) {
	var data map[string]interface{}
	sms, _ := factory.CreateSmsCodeService()
	data, err = sms.SendSms(request.Phone)
	rsp = &protocol.SmsCodeResponse{}
	if err != nil {
		if msg, ok := data["msg"]; ok {
			err = protocol.NewCustomMessage(1, msg.(string))
		}
		log.Error(err, data, request.Phone)
		return
	}
	err = protocol.NewSuccessWithMessage("发送验证码成功")
	return
}

func AccessToken(request *protocol.AccessTokenRequest) (rsp *protocol.AccessTokenResponse, err error) {
	var (
		claim *utils.UserTokenClaims
	)
	rsp = &protocol.AccessTokenResponse{}
	if claim, err = utils.ParseJWTToken(request.AuthCode); err != nil {
		err = protocol.NewErrWithMessage(4139, err)
		return
	}
	if claim.UserId <= 0 {
		err = protocol.NewErrWithMessage(1, fmt.Errorf("jwt authCode (%v) valid", request.AuthCode))
		return
	}
	rsp.AccessToken, _ = utils.GenerateToken(claim.UserId, protocol.TokenExpire*time.Second)
	rsp.RefreshToken, _ = utils.GenerateToken(claim.UserId, protocol.RefreshTokenExipre*time.Second)
	rsp.ExpiresIn = protocol.TokenExpire

	//auth := userAuth.NewRedisUserAuth(userAuth.WithUserId(claim.UserId),
	//	userAuth.WithAccessToken(rsp.AccessToken),
	//	userAuth.WithRefreshToken(rsp.RefreshToken))
	//if err = auth.AddAuth(); err != nil {
	//	log.Error(err)
	//	return
	//}
	return
}

func RefreshToken(request *protocol.RefreshTokenRequest) (rsp *protocol.RefreshTokenResponse, err error) {
	var (
		claim *utils.UserTokenClaims
	)
	rsp = &protocol.RefreshTokenResponse{}
	if claim, err = utils.ParseJWTToken(request.RefreshToken); err != nil {
		err = protocol.NewErrWithMessage(4140, err)
		return
	}
	if claim.UserId <= 0 {
		err = protocol.NewErrWithMessage(1, fmt.Errorf("jwt refrshToken (%v) valid", request.RefreshToken))
		return
	}
	//oldAuth := userAuth.NewRedisUserAuth(userAuth.WithUserId(claim.UserId))
	//if err = oldAuth.Check(userAuth.NewOptions(userAuth.WithRefreshToken(request.RefreshToken))); err != nil {
	//	log.Error(err)
	//	err = protocol.NewErrWithMessage(4140, err)
	//	return
	//}
	rsp.AccessToken, _ = utils.GenerateToken(claim.UserId, protocol.TokenExpire*time.Second)
	rsp.RefreshToken, _ = utils.GenerateToken(claim.UserId, protocol.RefreshTokenExipre*time.Second)
	rsp.ExpiresIn = protocol.TokenExpire

	//newAuth := userAuth.NewRedisUserAuth(userAuth.WithUserId(claim.UserId),
	//	userAuth.WithAccessToken(rsp.AccessToken),
	//	userAuth.WithRefreshToken(rsp.RefreshToken))
	//if err = newAuth.AddAuth(); err != nil {
	//	log.Error(err)
	//	return
	//}
	return
}

//验证短信验证码 T
func CheckSmsCode(phone, code string) (result bool, err error) {
	sms, _ := factory.CreateSmsCodeService()
	var data map[string]interface{}
	data, err = sms.CheckSmsCode(phone, code)
	if err != nil {
		if msg, ok := data["msg"]; ok {
			err = protocol.NewCustomMessage(1, msg.(string))
		}
		return
	}
	return
}

//验证手机号码(修改手机号码、重置密码的前一步)
func AuthCheckSmsCode(header *protocol.RequestHeader, request *protocol.AuthCheckSmsCodeRequest) (rsp *protocol.AuthCheckSmsCodeResponse, err error) {
	var ()
	if _, err = CheckSmsCode(request.Phone, request.Captcha); err != nil {
		return
	}
	rsp = &protocol.AuthCheckSmsCodeResponse{
		CaptchaCertificate: fmt.Sprintf("%v", utils.GenerateRangeNum(100000, 799999)),
	}
	return
}

//注销登录
func Revoke(header *protocol.RequestHeader, request *protocol.RevokeRequest) (rsp *protocol.RevokeResponse, err error) {
	//auth := userAuth.NewRedisUserAuth(userAuth.WithUserId(header.UserId))
	//rsp = &protocol.RevokeResponse{}
	//if !auth.Exist() {
	//	return
	//}
	//if err = auth.RemoveAuth(); err != nil {
	//	log.Error(err)
	//	err = protocol.NewErrWithMessage(4140, err)
	//	return
	//}
	return
}