package kuaidi

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"github.com/codinl/go-logger"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

type KdClient struct {
	UserId       string
	Secret       string
	Customer     string
	AuthorizeKey string
	BaseURL      string
}

var kdClient = &KdClient{
	UserId:       "a81ccda7168f4883ad5f0b0fe7e01f2c",
	Secret:       "33f57e255ad54e78b97ae3c32c81d522",
	Customer:     "B4F2CABA934E7EAD9D46C0DA2B50A689",
	AuthorizeKey: "JFZNvHAW3992",
	BaseURL:      "https://poll.kuaidi100.com/",
}

// JFZNvHAW3992
// 实时快递查询接口 /poll/query.do

func ExpressInfo(expressCompany, expressNum string) (*ExpressInfoResp, error) {
	resp := &ExpressInfoResp{}
	//type param struct {
	//
	//}
	//?customer=B4F2CABA934E7EAD9D46C0DA2B50A689&sign=2D8ADB6C424732F63F223C2665CAA1C1&param={"com":"emsbg","num":"9882823788521","from":"","phone":"",
	//"to":"","resultv2":"0","show":"0","order":"desc"}
	params := &url.Values{}
	param, err := getParam(expressCompany, expressNum)
	if err != nil {
		logger.Error("err:", err)
		return resp, err
	}
	kdSign := kdClient.getKdSign(param)
	params.Set("sign", kdSign)
	params.Set("param", param)

	fmt.Println("param", param)
	err = kdClient.post("/poll/query.do?", params, resp)
	if err != nil {
		logger.Info("err", err)
		return resp, err
	}
	respJson, _ := json.MarshalIndent(resp, "", "  ")
	//respJson, _ := json.Marshal(resp)
	fmt.Println("respJson:", string(respJson))

	return resp, nil
}

type ExpressInfoResp struct {
	Message   string `json:"message"`
	Nu        string `json:"nu"`
	Ischeck   string `json:"ischeck"`
	Condition string `json:"condition"`
	Com       string `json:"com"`
	Status    string `json:"status"`
	State     string `json:"state"`
	Data      []struct {
		Time    string `json:"time"`
		Ftime   string `json:"ftime"`
		Context string `json:"context"`
	} `json:"data"`
}

func (m *KdClient) post(kdApi string, params *url.Values, resp interface{}) error {
	params.Set("customer", m.Customer)
	uri := m.BaseURL + kdApi + params.Encode()
	//data, err := json.Marshal(req)
	//if err != nil {
	//	fmt.Println(err)
	//	return err
	//}

	res, err := http.Post(uri, "application/x-www-form-urlencoded", nil)
	if err != nil {
		fmt.Println(err)
		return err
	}
	//res.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	defer res.Body.Close()

	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return err
	}
	if err = json.Unmarshal(data, resp); err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func (m *KdClient) subscribePost(kdApi string, params *url.Values, resp interface{}) error {
	//params.Set("customer", m.Customer)
	uri := m.BaseURL + kdApi + params.Encode()
	fmt.Println("uri:", uri)

	res, err := http.Post(uri, "application/x-www-form-urlencoded", nil)
	if err != nil {
		fmt.Println(err)
		return err
	}
	//res.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	defer res.Body.Close()

	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return err
	}
	if err = json.Unmarshal(data, resp); err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func (m *KdClient) getKdSign(param string) string {
	//签名， 用于验证身份， 按param + key + customer 的顺序进行MD5加密（注意加密后字符串一定要转32位大写）， 不需要加上“+”号
	par := param + m.AuthorizeKey + m.Customer
	data := []byte(par)
	has := md5.Sum(data)
	md5str := fmt.Sprintf("%x", has) //将[]byte转成16进制
	return strings.ToUpper(md5str)
}

func getParam(company, num string) (string, error) {
	paramMap := map[string]interface{}{
		//"com":      "emsbg",
		//"num":      "9882823788521",
		"com":      company,
		"num":      num,
		"from":     "phone",
		"to":       "",
		"resultv2": "0",
		"show":     "0",
		"order":    "desc",
	}
	paramMapJson, err := json.Marshal(paramMap)
	if err != nil {
		logger.Error("err:", err)
		return "", err
	}
	return string(paramMapJson), nil
}

type SubscribeExpressStateResp struct {
	Result     bool   `json:"result"`
	ReturnCode string `json:"returnCode"`
	Message    string `json:"message"`
}

func SubscribeExpressState(expressCompanyNo, expressNum string) (*SubscribeExpressStateResp, error) {
	resp := &SubscribeExpressStateResp{}

	paramsMap := &map[string]interface{}{
		"company": expressCompanyNo,
		"number":  expressNum,
		"key":     kdClient.AuthorizeKey,
		"parameters": map[string]interface{}{
			"callbackurl": "https://admin.deovo.com:9521/goadminapi/api/v1/express/state_push", // 正式环境
			//"callbackurl": "https://dev.admin.deovo.com:9527/goadminapi/api/v1/express/state_push",// 测试环境
			"salt":     "FT1GHJ68798GJH3G",
			"resultv2": 1,
		},
	}

	paramsBytes, err := json.Marshal(paramsMap)
	if err != nil {
		logger.Error("err:", err)
		return resp, err
	}
	params := &url.Values{}
	params.Set("schema", "json")
	params.Set("param", string(paramsBytes))

	err = kdClient.subscribePost("/poll?", params, resp)
	if err != nil {
		logger.Info("err", err)
		return resp, err
	}
	respJson, _ := json.MarshalIndent(resp, "", "  ")
	//respJson, _ := json.Marshal(resp)
	fmt.Println("respJson:", string(respJson))

	return resp, nil
}
