package weixin

import (
	"errors"
	"strings"

	"git.rosy.net.cn/baseapi/platformapi/weixinapi"
	"git.rosy.net.cn/jx-callback/business/auth2"
	"git.rosy.net.cn/jx-callback/business/auth2/authprovider"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/globals"
	"git.rosy.net.cn/jx-callback/globals/api"
)

const (
	AuthTypeMini = "weixinmini" // 小程序
)

type MiniAuther struct {
	authprovider.DefAuther
}

var (
	ErrAuthTypeShouldBeMini = errors.New("当前操作要求是小程序登录方式")
)

var (
	AutherObjMini *MiniAuther
)

func init() {
	AutherObjMini = new(MiniAuther)
	auth2.RegisterAuther(AuthTypeMini, AutherObjMini)
}

func (a *MiniAuther) VerifySecret(dummy, jsCode string) (authBindEx *auth2.AuthBindEx, err error) {
	appID, jsCode := SplitJsCode(jsCode)
	sessionInfo, err := getWxApp(appID).SNSCode2Session(jsCode)
	if err == nil {
		sessionKey := sessionInfo.SessionKey
		sessionInfo.SessionKey = ""
		if authBindEx, err = a.UnionFindAuthBind(AuthTypeMini, getWxApp(appID).GetAppID(), []string{AuthTypeWeixin, AuthTypeMP, AuthTypeMini, AuthTypeWXNative}, sessionInfo.OpenID, sessionInfo.UnionID, sessionInfo); err == nil {
			authBindEx.UserData = sessionKey
		}
	}
	return authBindEx, err
}

// 特殊接口
func (a *MiniAuther) DecryptData(authInfo *auth2.AuthInfo, jsCode, encryptedData, iv string) (decryptedDataBase64 string, err error) {
	var sessionKey string
	appID, jsCode := SplitJsCode(jsCode)
	if jsCode != "" {
		sessionInfo, err := getWxApp(appID).SNSCode2Session(jsCode)
		if err == nil {
			// if authBindEx, err := a.UnionFindAuthBind(AuthTypeMini, getWxApp(appID).GetAppID(), []string{AuthTypeMini}, sessionInfo.OpenID, "", nil); err == nil {
			// if authBindEx.UserID != authInfo.GetID() {
			// 	return "", fmt.Errorf("jsCode与token不匹配")
			// }
			// } else {
			// 	return "", err
			// }
			sessionKey = sessionInfo.SessionKey
		} else {
			return "", err
		}
	} else {
		if authInfo.AuthBindInfo.Type != AuthTypeMini {
			// return "", ErrAuthTypeShouldBeMini
		}
		sessionKey = authInfo.AuthBindInfo.UserData.(string)
	}
	// decryptedData, err := ProxySNSDecodeMiniProgramData(encryptedData, sessionKey, iv)
	decryptedData, err := weixinapi.SNSDecodeMiniProgramData(encryptedData, sessionKey, iv)
	if err != nil {
		return "", err
	}
	// authInfo.AuthBindInfo.UserData = sessionKey
	return string(decryptedData), nil
}

func (a *MiniAuther) GetUserType() (userType int8) {
	return model.UserTypeStoreBoss
}

func getWxApp(appID string) (miniApi *weixinapi.API) {
	miniApi = api.WeixinMiniAPI
	if len(appID) > 0 && appID == api.WeixinMiniAppID2 {
		miniApi = api.WeixinMiniAPI2
	}
	if len(appID) > 0 && appID == api.WeixinMiniAppIDsc {
		miniApi = api.WeixinMiniAPIsc
	}
	//if len(appID) > 0 && appID == api.WeixinMiniPrintAppId {
	//	miniApi = api.WeixinMiniAPIPrint
	//}
	return miniApi
}

func SplitJsCode(jsCode string) (appID, realJsCode string) {
	list := strings.Split(jsCode, ",")
	if len(list) == 2 {
		appID = list[0]
		realJsCode = list[1]
	} else if len(list) == 1 {
		realJsCode = jsCode
	} else {
		globals.SugarLogger.Warnf("SplitJsCode abnormal jsCode:%s", jsCode)
	}
	return appID, realJsCode
}

func ComposeJsCode(appID, jsCode string) (composedCode string) {
	composedCode = strings.Join([]string{
		appID,
		jsCode,
	}, ",")
	return composedCode
}

// func ProxySNSCode2Session(jsCode string) (sessionInfo *weixinapi.SessionInfo, err error) {
// 	miniApi := api.WeixinMiniAPI
// 	list := strings.Split(jsCode, ",")
// 	if len(list) >= 2 && len(list[0]) == len("wx4b5930c13f8b1170") {
// 		if list[0] == api.WeixinMiniAppID2 {
// 			miniApi = api.WeixinMiniAPI2
// 		}
// 		miniApi = getWxApp(list[0])
// 		jsCode = strings.Join(list[1:], ",")
// 	}
// 	sessionInfo, err = miniApi.SNSCode2Session(jsCode)
// 	return sessionInfo, err
// }

// func ProxySNSDecodeMiniProgramData(encryptedData, sessionKey, iv string) (decryptedData []byte, err error) {
// 	globals.SugarLogger.Debugf("ProxySNSDecodeMiniProgramData, encryptedData:%s, sessionKey:%s, iv:%s", encryptedData, sessionKey, iv)
// 	decryptedData, err = api.WeixinMiniAPI.SNSDecodeMiniProgramData(encryptedData, sessionKey, iv)
// 	return decryptedData, err
// }
