package sso

import (
	"context"
	"encoding/base64"
	"errors"
	"eta/eta_mini_crm_ht/utils"
	"eta/eta_mini_crm_ht/utils/rpc"
	"fmt"
	"google.golang.org/grpc/metadata"
	"sync"
)

var (
	once           sync.Once
	rpcPool        utils.ClientPool
	SSOServiceImpl *SSOService
)

type SSOService struct {
	ssoRPCService
}
type ssoRPCService struct {
	rpc.DefaultRpcClient
}

func GetSSOService() *SSOService {
	once.Do(func() {
		c := ssoRPCService{}
		rpcPool = c.GetPool(utils.SSO_URL)
		SSOServiceImpl = &SSOService{c}
	})
	return SSOServiceImpl
}

type UserResp struct {
	UserName string
}

func (s *SSOService) SSOLogin(request *LoginRequest) (resp UserResp, err error) {
	conn := rpcPool.Get()
	defer rpcPool.Put(conn)
	ssoLoginService := NewSSOLoginClient(conn)
	aesKey, err := utils.GenerateAESKey(16)
	if err != nil {
		utils.FileLog.Error("生成AES密钥失败:%v", err)
		return
	}
	encryptedCode, err := utils.EncryptWithAES(aesKey, []byte(request.Code))
	if err != nil {
		utils.FileLog.Error("AES加密失败:%v", err)
		return
	}
	request.Code = base64Encode(encryptedCode)
	publicKey, err := utils.ParsePublicKeyFromPEM()
	if err != nil {
		utils.FileLog.Error("RSA加密失败:%v", err)
		return
	}
	//加密 AES 密钥
	encryptedAESKey, err := utils.EncryptWithRSA(publicKey, aesKey)
	if err != nil {
		utils.FileLog.Error("encrypting AES key: %v", err)
		return
	}
	key := base64Encode(encryptedAESKey)
	ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(
		"key", key,
	))
	ssoResp, err := ssoLoginService.Login(ctx, request)
	if err != nil {
		utils.FileLog.Error("sso login failed:%v", err)
		return
	}
	if ssoResp.ErrCode != 0 {
		err = errors.New(fmt.Sprintf("sso登录失败:%s", ssoResp.ErrMsg))
		utils.FileLog.Error("sso登录失败:%v", ssoResp.ErrMsg)
		return
	}
	userinfo := ssoResp.Data
	utils.FileLog.Info("sso请求成功")
	resp = UserResp{
		UserName: userinfo.Username,
	}
	return
}
func base64Encode(data []byte) string {
	return base64.StdEncoding.EncodeToString(data)
}

// Base64Decode 对数据进行 Base64 解码
func base64Decode(data string) ([]byte, error) {
	return base64.StdEncoding.DecodeString(data)
}