package cooper

import (
	"PPOSUtils/utils"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"sync"
	"time"
)

type OrderRequest struct {
	appID         int64    //应用ID
	companyID     int64    //公司ID
	sysID         int64    //子系统ID
	businessID    int64    //商户ID
	salesID       int64    //营业点ID
	stadiumID     int64    //场馆ID
	authorization string   //jwt认证
	params        utils.Mp //params..
	exception     utils.Mp //error..
	hostClient    *HostClient
	host          string
	chanLock      sync.Mutex
}

//new...(appID,sysID,businessID,jwt...)
func (that *OrderRequest) NewOrder(params ...interface{}) *OrderRequest {
	return newOrder(params...)
}

//new2...(appID,sysID,businessID,jwt...)
func NewOrder(params ...interface{}) *OrderRequest {
	return newOrder(params...)
}

//new3...(appId, apiKey, apiDomain...)
func NewHostClient(appId, apiKey, apiDomain string) *HostClient {
	return &HostClient{
		appId:     appId,
		apiKey:    apiKey,
		apiDomain: apiDomain,
	}
}

//HostClient...
type HostClient struct {
	appId     string
	apiKey    string
	apiDomain string
}

//new...
func newOrder(params ...interface{}) *OrderRequest {
	that := &OrderRequest{
		params: utils.NewMP(),
	}
	if that.hostClient == nil {
		that.hostClient = NewHostClient("", "", "")
	}
	if len(params) > 0 {
		that.SetAppID(utils.ToInt64(params[0]))
	}
	if len(params) > 1 {
		that.SetSysID(utils.ToInt64(params[1]))
	}
	if len(params) > 2 {
		that.SetBusinessID(utils.ToInt64(params[2]))
	}
	if len(params) > 3 {
		that.SetJwt(utils.ToString(params[3]))
	}
	that.exception = nil
	return that
}

//Interface...
type OrderRequestInterface interface {
	NewOrder(params ...interface{}) *OrderRequest            //初始化Interface
	SetAppID(appID int64) *OrderRequest                      //设置应用ID
	SetJwt(jwt string) *OrderRequest                         //设置jwt登录认证
	SetCompanyID(companyID int64) *OrderRequest              //设置公司ID
	SetBusinessID(businessID int64) *OrderRequest            //设置商户ID
	SetSysID(sysID int64) *OrderRequest                      //设置子系统ID
	SetStadiumID(stadiumID int64) *OrderRequest              //设置场馆ID
	SetSalesID(salesID int64) *OrderRequest                  //设置营业点ID
	GetException() utils.Mp                                  //获取异常
	SetException(data utils.Mp, params ...string)            //设置异常
	SetParam(key string, value interface{}) *OrderRequest    //设置某一个key参数
	SetParams(params utils.Mp) *OrderRequest                 //批量设置参数
	GetParam(key string) interface{}                         //获取指定key请求参数
	GetParamAll() utils.Mp                                   //获取所有请求参数
	Curl(url string) (utils.Mp, error)                       //普通post请求
	CurlForChan(url string, ch chan<- interface{})           //请求带chan信道
	SetShopCartParams(mp utils.Mp)                           //设置购物车参数
	SetAsyncNoticeParams(mp utils.Mp)                        //设置回调shop参数
	SetPayQueryParams(mp utils.Mp)                           //设置支付查询参数
	ClearParamMp() *OrderRequest                             //清空请求参数
	UrlPost(apiUrl string, param utils.Mp) (utils.Mp, error) //发送post请求
	SetHostClient(params *HostClient) *OrderRequest          //设置一个带签名的Client
	SetCooperClient(params *CooperClient) *OrderRequest      ///设置一个带签名的Cooper
	SetHost(host string) *OrderRequest                       //重写host的Client
}

//set...
func (that *OrderRequest) SetAppID(appID int64) *OrderRequest {
	that.appID = appID
	return that
}
func (that *OrderRequest) SetJwt(jwt string) *OrderRequest {
	that.authorization = jwt
	return that
}
func (that *OrderRequest) SetBusinessID(businessID int64) *OrderRequest {
	that.businessID = businessID
	return that
}
func (that *OrderRequest) SetCompanyID(value int64) *OrderRequest {
	that.companyID = value
	return that
}
func (that *OrderRequest) SetSalesID(salesID int64) *OrderRequest {
	that.salesID = salesID
	return that
}
func (that *OrderRequest) SetStadiumID(stadiumID int64) *OrderRequest {
	that.stadiumID = stadiumID
	return that
}
func (that *OrderRequest) SetSysID(sysID int64) *OrderRequest {
	that.sysID = sysID
	return that
}
func (that *OrderRequest) SetException(data utils.Mp, params ...string) {
	that.exception = utils.NewMP()
	if len(params) > 0 {
		that.exception["describe"] = params[0] //错误描述
		return
	}
	that.exception = data
}
func (that *OrderRequest) GetException() utils.Mp {
	return that.exception
}

//SetParam...
func (that *OrderRequest) SetParam(key string, value interface{}) *OrderRequest {
	that.params[key] = value
	return that
}

//SetParams...
func (that *OrderRequest) SetParams(params utils.Mp) *OrderRequest {
	for key, val := range params {
		that.params[key] = val
	}
	return that
}

//set cooper签名属性..
func (that *OrderRequest) SetHostClient(params *HostClient) *OrderRequest {
	that.hostClient = params
	return that
}
func (that *OrderRequest) SetCooperClient(params *CooperClient) *OrderRequest {
	that.hostClient.apiKey = params.apiKey
	that.hostClient.apiDomain = params.apiDomain
	that.hostClient.appId = params.appId
	return that
}

//SetHost...
func (that *OrderRequest) SetHost(host string) *OrderRequest {
	that.host = host
	return that
}

//GetParam...
func (that *OrderRequest) GetParam(key string) interface{} {
	return that.params[key]
}

//ClearParamMp...
func (that *OrderRequest) ClearParamMp() *OrderRequest {
	that.params = utils.NewMP()
	return that
}

//getAll... 必填项
func (that *OrderRequest) GetParamAll() utils.Mp {
	that.chanLock.Lock()
	defer that.chanLock.Unlock()
	//
	that.params["app_id"] = that.appID                //appID
	that.params["authorization"] = that.authorization //jwt，登录认证
	if that.companyID != 0 {
		that.params["company_id"] = that.companyID //公司ID，可选
	}
	if that.businessID != 0 {
		that.params["business_id"] = that.businessID //商户ID，可选
	}
	if that.sysID != 0 {
		that.params["sys_id"] = that.sysID //子系统ID，可选
	}
	if that.salesID != 0 {
		that.params["sales_id"] = that.salesID //营业点ID，可选
	}
	if that.stadiumID != 0 {
		that.params["stadium_id"] = that.stadiumID //场馆ID，可选
	}
	return that.params
}

//go Curl to POST ...
func (that *OrderRequest) Curl(url string) (utils.Mp, error) {
	_data, _exp := that.UrlPost(url, that.GetParamAll())
	//err ...
	if _exp != nil {
		that.SetException(_data)
		return that.exception, _exp
	}
	return _data, nil
}

//go chan Curl to POST ... for make(chan interface{})
func (that *OrderRequest) CurlForChan(url string, ch chan<- interface{}) {
	_data, _exp := that.UrlPost(url, that.GetParamAll())
	//err ...
	if _exp != nil {
		that.SetException(_data)
		ch <- _exp.Error()
		return
	}
	fmt.Println("-------chan创建中--------", _data["data"])
	ch <- _data["data"]

}

//SetShopCartParams ...需要根据不同的子系统(sys_id)去请求不同的添加购物车
func (that *OrderRequest) SetShopCartParams(mp utils.Mp) {
	_slice := []string{"sku_slice"}
	for _, v := range _slice {
		if mp.Has(v) && v == "sku_slice" { //不带冒号的sku..
			that.SetParam(v, mp[v])
		}
		//...
	}
}

//SetAsyncNoticeParams ... 去通知子系统异步回调...
func (that *OrderRequest) SetAsyncNoticeParams(mp utils.Mp) {
	_slice := []string{"order_no", "trade_no", "member_card_id", "payment_way", "transaction_id", "buyer_user_id"}
	for _, v := range _slice {
		if mp.Has(v) && v == "order_no" { //订单号
			that.SetParam(v, mp[v])
		}
		if mp.Has(v) && v == "trade_no" { //交易号
			that.SetParam(v, mp[v])
		}
		if mp.Has(v) && v == "member_card_id" { //会员一卡通
			that.SetParam(v, mp[v])
		}
		if mp.Has(v) && v == "payment_way" { //测试支付宝支付
			that.SetParam(v, mp[v])
		}
		if mp.Has(v) && v == "transaction_id" { //第三方交易号
			that.SetParam(v, mp[v])
		}
		if mp.Has(v) && v == "buyer_user_id" { //买家支付标识ID
			that.SetParam(v, mp[v])
		}
	}
}

//SetPayQueryParams.. 去查询支付系统的订单状态...
func (that *OrderRequest) SetPayQueryParams(mp utils.Mp) {
	_slice := []string{"transaction_id", "out_trade_no"}
	for _, v := range _slice {
		if mp.Has(v) && v == "transaction_id" { //第三方的交易号(二选一)
			that.SetParam(v, mp[v])
		}
		if mp.Has(v) && v == "out_trade_no" { //交易号 (二选一)
			that.SetParam(v, mp[v])
		}
	}
}

/*
 *发送post请求   Author:tang
 *@param apiUrl api地址
 *@param postParam post参数
 *@param result map格式解析json数据， err error对象
 */
func (that *OrderRequest) UrlPost(apiUrl string, param utils.Mp) (utils.Mp, error) {
	if apiUrl == "" {
		return nil, errors.New("Please check the request address. ")
	}
	v := url.Values{}
	//
	for key, value := range param {
		v.Set(key, ToString(value))
	}
	_apiUrl := apiUrl
	//cooper的签名算法验证..
	if that.hostClient.apiKey != "" {
		v.Del("sign")
		sign := utils.SignMD5(that.hostClient.apiKey, v)
		v.Set("sign", sign)
		apiUrl = that.hostClient.apiDomain + _apiUrl
	}
	//
	if that.host != "" {
		apiUrl = that.host + _apiUrl
	}
	//
	fmt.Println("================vvv===================to", apiUrl, "params:", v)
	//
	u, _ := url.ParseRequestURI(apiUrl)
	urlStr := u.String()
	client := &http.Client{
		//超时timeOut时间
		Timeout: 9 * time.Second,
	}
	r, _ := http.NewRequest("POST", urlStr, strings.NewReader(v.Encode())) // URL-encoded payload
	r.Header.Add("Content-Type", "application/x-www-form-urlencoded")      //添加请求头Type
	r.Header.Add("Content-Length", strconv.Itoa(len(v.Encode())))          //添加请求头Length
	r.Header.Add("Authorization", ToString(param["authorization"]))        //添加请求头token

	resp, err := client.Do(r)
	if err != nil {
		if strings.Contains(err.Error(), "timeout") {
			fmt.Println("----------HttpLog---------", apiUrl+"请求超时TimeOut")
			return nil, errors.New("请求超时TimeOut")
		}
		if strings.Contains(err.Error(), "Client.Timeout exceeded") {
			fmt.Println("----------HttpLog---------", apiUrl+"请求超时TimeOut2")
			return nil, errors.New("请求超时TimeOut2")
		}
		return nil, err
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	obj := utils.Mp{}
	err = json.Unmarshal([]byte(body), &obj)
	if obj.Has("code") {
		if _, _code := obj.Get("code").(float64); !_code {
			return obj, errors.New(ToString(obj.Get("message")))
		}
	}
	if obj.Has("code") && ToInt64(obj.Get("code")) != 200 {
		if obj.Has("message") {
			return obj, errors.New(ToString(obj.Get("message")))
		}
		return obj, errors.New(ToString(obj.Get("msg")))
	}
	if obj.Has("data") {
		return obj, nil
	}
	return obj, nil
}
