package services

import (
	"PaymentCenter/app/constants/common"
	"PaymentCenter/app/constants/errorcode"
	"PaymentCenter/app/http/entities/front"
	"PaymentCenter/app/models/appmodel"
	"PaymentCenter/app/services/apicrypt"
	"PaymentCenter/app/utils"
	"github.com/bytedance/sonic"
	"strings"
)

type AppCheck struct {
	AppId int64
	Ip    string
	App   *appmodel.App
	Code  int
}

func NewAppCheck(app *appmodel.App) *AppCheck {
	return &AppCheck{
		App:  app,
		Code: errorcode.Success,
	}
}

func (a *AppCheck) IpCheck(ip string) bool {
	if a.App.WhiteIp == "" {
		return true
	}
	if !utils.ContainsString(strings.Split(a.App.WhiteIp, ","), ip) {
		a.Code = errorcode.AppIpNotAllow
		return false
	}
	return true
}

func (a *AppCheck) Check() *AppCheck {

	if a.App.Status == common.STATUS_DISABLED {
		a.Code = errorcode.AppDisabled
		return a
	}

	return a
}

func (a *AppCheck) GetCode() int {
	return a.Code
}

func (a *AppCheck) Crypt() (cryptFunc func(app *appmodel.App) apicrypt.ApiCrypt) {
	var (
		ok bool
	)
	if cryptFunc, ok = apicrypt.ApiCryptMap[a.App.KeyType]; !ok {
		a.Code = errorcode.AppNotFound
		return nil
	}
	return cryptFunc
}

func (a *AppCheck) ReCheckAfterDecrypt(data []byte, requestData *front.RequestBody) bool {
	var requestCommonData front.ApiCommonBody
	if err := sonic.Unmarshal(data, &requestCommonData); err != nil {
		a.Code = errorcode.ParamError
		return false
	}
	if requestCommonData.AppId != requestData.AppId || requestCommonData.Timestamp != requestData.Timestamp {
		a.Code = errorcode.AppDecryptDataDiscrepancy
		return false
	}
	return true
}