package tibiotapi

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"git.rosy.net.cn/baseapi/platformapi"
	"git.rosy.net.cn/baseapi/utils"
	"net/http"
	"strings"
	"time"
)

const (
	prodURL = "https://api.tibiot.cn/api/v1"
	signKey = "password"
)

const (
	// ResponseCodeSuccess 操作成功
	ResponseCodeSuccess = 0
)

type API struct {
	platformapi.APICookie

	username string
	password string
	client   *http.Client
	config   *platformapi.APIConfig
}

func New(username, password string, config ...*platformapi.APIConfig) *API {
	curConfig := platformapi.DefAPIConfig
	if len(config) > 0 {
		curConfig = *config[0]
	}
	return &API{
		username: username,
		password: password,
		client:   &http.Client{Timeout: curConfig.ClientTimeout},
		config:   &curConfig,
	}
}

func (a *API) signParams(apiParams map[string]interface{}) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%x", md5.Sum([]byte(a.password)))+apiParams["tkey"].(string))))
}

func (a *API) AccessAPI(url string, apiParams map[string]interface{}, isJson bool) (retVal map[string]interface{}, err error) {
	params := utils.MergeMaps(map[string]interface{}{
		"username": a.username,
	}, apiParams)
	fullURL := utils.GenerateGetURL(prodURL, url, nil)
	err = platformapi.AccessPlatformAPIWithRetry(a.client,
		func() *http.Request {
			tkey := time.Now().Format("20060102150405")
			params["tkey"] = tkey
			sign := a.signParams(params)
			params[signKey] = sign
			var request *http.Request
			if isJson {
				delete(params, "username")
				delete(params, "password")
				delete(params, "tkey")
				params["userName"] = a.username
				params["passWord"] = sign
				params["tKey"] = tkey
				data, _ := json.Marshal(params)
				request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
				request.Header.Set("Content-Type", "application/json")
			} else {
				request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
				request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
			}
			return request
		},
		a.config,
		func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
			if jsonResult1 == nil {
				return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
			}
			code := int(utils.Interface2Int64WithDefault(jsonResult1["status"], ResponseCodeSuccess))
			if code == ResponseCodeSuccess {
				if jsonResult1["data"] != nil {
					retVal = jsonResult1["data"].(map[string]interface{})
				} else {
					retVal = nil
				}
				return platformapi.ErrLevelSuccess, nil
			}
			newErr := utils.NewErrorIntCode(jsonResult1["message"].(string), code)
			return platformapi.ErrLevelCodeIsNotOK, newErr
		})
	return retVal, err
}

type GetCardInfoResult struct {
	CardStatus string `json:"card_status"` //卡状态 1 - 正常 2 - 停机 3 - 待激活
	Iccid      string `json:"iccid"`
	Msisdn     string `json:"msisdn"`
	CardType   string `json:"card_type"` //卡类型 1 - 单卡 2 - 池卡
	Imsi       string `json:"imsi"`
}

func (a *API) GetCardInfo(iccid string) (getCardInfoResult *GetCardInfoResult, err error) {
	result, err := a.AccessAPI("card/getCardInfo", map[string]interface{}{
		"iccid": iccid,
	}, false)
	if err == nil {
		utils.Map2StructByJson(result, &getCardInfoResult, false)
	}
	return getCardInfoResult, err
}

type BatchQueryCardInfoResult struct {
	PageNum    int         `json:"pageNum"`
	PageSize   int         `json:"pageSize"`
	TotalCount int         `json:"totalCount"`
	PageCount  int         `json:"pageCount"`
	OrderBy    interface{} `json:"orderBy"`
	Records    []struct {
		Iccid        string `json:"iccid"`
		Msisdn       string `json:"msisdn"`
		Cardstatus   int    `json:"cardStatus"`
		Operator     int    `json:"operator"`
		Packagename  string `json:"packageName"`
		Totalflow    string `json:"totalFlow"`
		Cardflow     string `json:"cardFlow"`
		Leftflow     string `json:"leftFlow"`
		Opencardtime string `json:"openCardTime"`
		Activatetime string `json:"activateTime"`
		Packagetime  string `json:"packageTime"`
		PrintNo      string `json:"print_no"`
		Name         string `json:"name"`
	} `json:"records"`
}

type BatchQueryCardInfoParam struct {
	IccID            string `json:"iccid,omitempty"`
	CardStatus       int    `json:"cardStatus,omitempty"`
	CardType         int    `json:"cardType,omitempty"`
	PageNum          int    `json:"pageNum,omitempty"`
	PageSize         int    `json:"pageSize,omitempty"`
	BeginPackageTime string `json:"beginPackageTime,omitempty"`
	EndPackageTime   string `json:"endPackageTime,omitempty"`
}

func (a *API) BatchQueryCardInfo(batchQueryCardInfoParam *BatchQueryCardInfoParam) (batchQueryCardInfoResult *BatchQueryCardInfoResult, err error) {
	result, err := a.AccessAPI("card/batchQueryCardInfo", utils.Struct2FlatMap(batchQueryCardInfoParam), true)
	if err == nil {
		utils.Map2StructByJson(result, &batchQueryCardInfoResult, false)
	}
	return batchQueryCardInfoResult, err
}

type IotDataResult struct {
	SyncStatus string `json:"sync_status"` // 1 未同步， 2已同步
	CardFlow   string `json:"card_flow"`
	CreateTime string `json:"create_time"`
	SyncTime   string `json:"sync_time"`
}

func (a *API) IotData(iccid, queryTime string) (getCardInfoResult *IotDataResult, err error) {
	result, err := a.AccessAPI("card/iotData", map[string]interface{}{
		"iccid":      iccid,
		"query_time": queryTime,
	}, false)
	if err == nil && result != nil {
		utils.Map2StructByJson(result, &getCardInfoResult, false)
	}
	return getCardInfoResult, err
}

type IotDataMonthResult struct {
	CardFlow     string `json:"card_flow"`
	TotalFlow    string `json:"total_flow"`
	LeftFlow     string `json:"left_flow"`
	PackageName  string `json:"package_name"`
	ActivateTime string `json:"activate_time"`
	PackageTime  string `json:"package_time"`
}

func (a *API) IotDataMonth(iccid string) (getCardInfoResult *IotDataMonthResult, err error) {
	result, err := a.AccessAPI("card/iotData", map[string]interface{}{
		"iccid":     iccid,
		"card_type": 1,
	}, false)
	if err == nil && result != nil {
		utils.Map2StructByJson(result, &getCardInfoResult, false)
	}
	return getCardInfoResult, err
}

func (a *API) CardActivation(iccid string) (getCardInfoResult *GetCardInfoResult, err error) {
	result, err := a.AccessAPI("card/cardActivation", map[string]interface{}{
		"iccid": iccid,
	}, true)
	if err == nil && result != nil {
		utils.Map2StructByJson(result, &getCardInfoResult, false)
	}
	return getCardInfoResult, err
}

//卡续费
//duration 续费时长，非必填，月默认12月 其余周期默认1
func (a *API) Submit(iccid string, duration int) (getCardInfoResult *GetCardInfoResult, err error) {
	result, err := a.AccessAPI("renew/submit", map[string]interface{}{
		"iccid":    iccid,
		"duration": duration,
	}, true)
	if err == nil && result != nil {
		utils.Map2StructByJson(result, &getCardInfoResult, false)
	}
	return getCardInfoResult, err
}
