package cooper

import (
	"PPOSUtils/utils"
	"errors"
	"fmt"
	"github.com/imroc/req"
	"math/rand"
	"net/http"
	"net/url"
	"strings"
	"time"
)

func NewCooperClient(appId, apiKey, apiDomain string) *CooperClient {
	return &CooperClient{
		appId:     appId,
		apiKey:    apiKey,
		apiDomain: apiDomain,
	}
}

//ClientParam ...
type ClientParam interface {
	// 返回参数列表
	Params() (url.Values, error)
}

//CooperClient ...
type CooperClient struct {
	appId          string
	apiKey         string
	apiDomain      string
	timeOut        int
	responseCode   int64
	requestAddress string
}

//在这里添加耗时比较长的SDK接口
var ApiLongTimeMp = utils.SliceString{
	"/baiduFace/search",
	"/baiduFace/userAdd",
	"/baiduFace/userUpdate",
	"/hand/checkUser",
	"/hand/sendRing",
	"/hand/checkBackRing",
	"/hand/returnRing",
	"/usrK3/cmd",
	"/usrK3/query",
}

var ApiLongTimeMp2 = utils.SliceString{
	"/pay/umsPos",
	"/pay/umsOpenPos",
}

func (that *CooperClient) SetTimeOut(second int) *CooperClient {
	that.timeOut = second
	return that
}

//获取错误码
func (that *CooperClient) GetResponseCode() int64 {
	return that.responseCode
}

//_URLValues ...
func (that *CooperClient) _getURLValues(param ClientParam) (value url.Values, err error) {
	p, _err := param.Params()
	if _err != nil {
		return nil, _err
	}
	fmt.Println("params", p)
	p.Set("app_id", that.appId)
	p.Set("nonce_str", that.getNonceStr())
	var sign = utils.SignMD5(that.apiKey, p)
	p.Set("sign", sign)
	return p, nil
}

func (that *CooperClient) longTimeInterface(url string) int {
	_defaultOutTime := 5
	if ApiLongTimeMp.In(url) {
		_defaultOutTime = 15
	}
	return that.longLongTimeInterface(url, _defaultOutTime)
}

func (that *CooperClient) longLongTimeInterface(url string, outTime int) int {
	if ApiLongTimeMp2.In(url) {
		return 15 * 4
	}
	return outTime
}

func (that *CooperClient) GetTimeOut(url string) time.Duration {
	return time.Duration(that.longTimeInterface(url))
}

//代理..
func (that *CooperClient) Proxy(url string, param ClientParam, method string, v ...interface{}) (http.Header, []byte, error) {
	_method := "post"
	if len(method) > 0 {
		_method = strings.ToLower(method)
	}
	var _resp *req.Resp
	var _err error
	switch _method {
	case "post":
		_resp, _err = that.proxyPost(url, param, v...)
	case "get":
		_resp, _err = that.proxyGet(url, param, v...)
	}
	if _err != nil {
		return nil, nil, _err
	}
	_body, _err := _resp.ToBytes()
	_header := _resp.Response().Header
	return _header, _body, _err
}

//POST代理..
func (that *CooperClient) proxyPost(url string, param ClientParam, v ...interface{}) (*req.Resp, error) {
	_URLValues, _err := that._getURLValues(param)
	if _err != nil {
		return nil, _err
	}
	_sign := "Signature-ppos-pro/" + _URLValues.Get("sign")
	_header := make(http.Header)
	_header.Add("Authorization", _sign)
	_URLValues.Del("sign")
	v = append(v, _URLValues, _header)
	req.SetTimeout(that.GetTimeOut(url) * time.Second)
	return req.Post(that._buildAPI(url), v...)
}

//Get代理
func (that *CooperClient) proxyGet(url string, param ClientParam, v ...interface{}) (*req.Resp, error) {
	_URLValues, _err := that._getURLValues(param)
	if _err != nil {
		return nil, _err
	}
	url = that._buildAPI(url)
	fmt.Println(url, _URLValues)
	v = append(v, _URLValues)
	req.SetTimeout(that.GetTimeOut(url) * time.Second)
	return req.Get(url, v...)
}

//Post ...
func (that *CooperClient) Post(url string, param ClientParam) (interface{}, error) {
	that.responseCode = 0
	that.requestAddress = url
	_URLValues, _err := that._getURLValues(param)
	if _err != nil {
		return nil, _err
	}
	_header := req.Header{
		"Accept":       "application/json",
		"Content-Type": "application/x-www-form-urlencoded",
	}
	_timeOut := that.GetTimeOut(url)
	//fmt.Println("++++cooperTimeOut++++", _timeOut)
	req.SetTimeout(_timeOut * time.Second)
	_resp, _err := req.Post(that._buildAPI(url), _URLValues, _header)
	fmt.Println("cooper请求响应结果：", _resp)
	if _err != nil {
		return nil, _err
	}
	_result := map[string]interface{}{}
	if _err := _resp.ToJSON(&_result); _err != nil {
		return nil, _err
	}
	_slice := []string{
		"code",
		"message",
		"data",
	}
	for _, _v := range _slice {
		if _, _ok := _result[_v]; !_ok {
			return nil, errors.New("")
		}
	}
	that.responseCode = ToInt64(_result["code"])
	if that.responseCode != 200 {
		return _result["code"], errors.New(ToString(_result["message"]))
	}
	return _result["data"], nil
}

//BuildAPI ...
func (that *CooperClient) _buildAPI(paths ...string) string {
	var path = that.apiDomain
	for _, p := range paths {
		p = strings.TrimSpace(p)
		if len(p) > 0 {
			if strings.HasSuffix(path, "/") {
				path = path + p
			} else {
				if strings.HasPrefix(p, "/") {
					path = path + p
				} else {
					path = path + "/" + p
				}
			}
		}
	}
	return path
}

func (that *CooperClient) getNonceStr() (nonceStr string) {
	chars := "abcdefghijklmnopqrstuvwxyz0123456789"
	for i := 0; i < 32; i++ {
		idx := rand.Intn(len(chars) - 1)
		nonceStr += chars[idx : idx+1]
	}
	return nonceStr
}
