package xpyunapi

import (
	"errors"
	"fmt"
	"git.rosy.net.cn/baseapi/platformapi"
	"net/http"
	"strconv"
	"strings"
	"sync"
)

const (
	baseURL      = "https://open.xpyun.net/api/openapi/xprinter/"
	signKey      = "sign"
	timestampKey = "timestamp"
	debugTest    = 1 //debug=1返回非json格式的数据，仅测试时候使用
)

const (
	ResponseCodeSuccess = 0 //成功
	ResponseMsgSuccess  = "ok"
)

var (
	exceedLimitCodes = map[string]int{}
	canRetryCodes    = map[string]int{}
)

type API struct {
	locker      sync.RWMutex
	accessToken string

	userName string
	userKey  string
	client   *http.Client
	config   *platformapi.APIConfig
}

//初始化
func New(userName, userKey string, config ...*platformapi.APIConfig) *API {
	curConfig := platformapi.DefAPIConfig
	if len(config) > 0 {
		curConfig = *config[0]
	}
	return &API{
		userName: userName,
		userKey:  userKey,
		client:   &http.Client{Timeout: curConfig.ClientTimeout},
		config:   &curConfig,
	}
}

//生成签名
func (a *API) GenerateSign() string {
	return Sign(a.userName + a.userKey + strconv.FormatInt(GetMillisecond(), 10))
}

//生成 RestRequest
func (a *API) GenerateRestRequest() RestRequest {
	return RestRequest{
		User:      a.userName,
		UserKey:   a.userKey,
		Timestamp: GetMillisecond(),
		Sign:      a.GenerateSign(),
	}
}

func xpyunPostJson(url string, request interface{}) *XPYunResp {
	result := HttpPostJson(url, request)
	return result
}

// 1.添加打印机到开发者账户（可批量）
func (a *API) AddPrinters(sn, printerName string) error {
	url := baseURL + "addPrinters"
	request := &AddPrinterRequest{
		RestRequest: a.GenerateRestRequest(),
		Items: []*AddPrinterRequestItem{{
			Sn:   sn,
			Name: printerName,
		}},
	}
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	retVal, _ := resp.Content.Data.(map[string]interface{})
	failMsg := ""
	if len(retVal["failMsg"].([]interface{})) > 0 {
		for _, v := range retVal["failMsg"].([]interface{}) {
			t := strings.Split(v.(string), ":")
			failMsg += t[0] + XpuErrMsg[t[1]]
		}

		return fmt.Errorf("添加打印机错误：%v", failMsg)
	}
	return nil
}

//2.设置打印机语音类型
func (a *API) SetVoiceType(sn string, soundSize int) error {
	url := baseURL + "setVoiceType"
	request := &SetVoiceTypeRequest{
		RestRequest: a.GenerateRestRequest(),
		Sn:          sn,
		VoiceType:   VoiceTypeOtherPerson,
		VolumeLevel: soundSize,
	}
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	retVal, _ := resp.Content.Data.(map[string]interface{})
	failMsg := ""
	if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
		for _, v := range retVal["failMsg"].([]interface{}) {
			t := strings.Split(v.(string), ":")
			failMsg += t[0] + XpuErrMsg[t[1]]
		}
		return fmt.Errorf("设置打印机运营类型错误：%v", failMsg)
	}
	return nil
}

//3.打印小票订单
func (a *API) Print(request *PrintRequest) (string, error) {
	url := baseURL + "print"
	request.RestRequest = a.GenerateRestRequest()
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return "0", errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return "0", fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	retVal, _ := resp.Content.Data.(string)
	if len(retVal) > 0 {
		return retVal, nil
	} else {
		return "0", nil
	}
}

// 5.批量删除打印机
func (a *API) DelPrinters(snList []string) error {
	url := baseURL + "delPrinters"
	request := &DelPrinterRequest{
		RestRequest: a.GenerateRestRequest(),
		SnList:      snList,
	}
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	retVal, _ := resp.Content.Data.(map[string]interface{})
	failMsg := ""
	if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
		for _, v := range retVal["failMsg"].([]interface{}) {
			t := strings.Split(v.(string), ":")
			failMsg += t[0] + XpuErrMsg[t[1]]
		}
		return fmt.Errorf("删除打印机错误：%v", failMsg)
	}
	return nil
}

//6.修改打印机信息
func (a *API) UpdatePrinter(request *UpdPrinterRequest) error {
	url := baseURL + "updPrinter"
	request.RestRequest = a.GenerateRestRequest()
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	retVal, _ := resp.Content.Data.(map[string]interface{})
	failMsg := ""
	if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
		for _, v := range retVal["failMsg"].([]interface{}) {
			t := strings.Split(v.(string), ":")
			failMsg += t[0] + XpuErrMsg[t[1]]
		}
		return fmt.Errorf("修改打印机信息错误：%v", failMsg)
	}
	return nil
}

//7.清空待打印队列
func (a *API) EmptyPrinterQueue(sn string) error {
	url := baseURL + "delPrinterQueue"
	request := &EmpPrinterQueueRequest{
		RestRequest: a.GenerateRestRequest(),
		Sn:          sn,
	}
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return fmt.Errorf("%v", XpuErrMsg[resp.Content.Msg])
	}
	retVal, _ := resp.Content.Data.(map[string]interface{})
	failMsg := ""
	if retVal != nil && len(retVal["failMsg"].([]interface{})) > 0 {
		for _, v := range retVal["failMsg"].([]interface{}) {
			t := strings.Split(v.(string), ":")
			failMsg += t[0] + XpuErrMsg[t[1]]
		}
		return fmt.Errorf("清空待打印机队列错误：%v", failMsg)
	}
	return nil
}

//8.查询订单状态
func (a *API) QueryOrderState(request *QueryOrderStateRequest) (bool, error) {
	url := baseURL + "queryOrderState"
	request.RestRequest = a.GenerateRestRequest()
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return false, errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return false, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	return resp.Content.Data.(bool), nil
}

//9.查询打印机某天的订单统计数
func (a *API) QueryOrderStatis(request *QueryOrderStatisRequest) (printed, waiting float64, err error) {
	url := baseURL + "queryOrderStatis"
	request.RestRequest = a.GenerateRestRequest()
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return 0, 0, errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return 0, 0, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	retVal, _ := resp.Content.Data.(map[string]interface{})
	if retVal != nil {
		printed = retVal["printed"].(float64)
		waiting = retVal["waiting"].(float64)
		return printed, waiting, nil
	}
	return 0, 0, nil
}

//10.获取指定打印机状态
//* 0、离线 1、在线正常 2、在线不正常
// * 备注：异常一般是无纸，离线的判断是打印机与服务器失去联系超过30秒
func (a *API) QueryPrinterStatus(sn string) (interface{}, error) {
	url := baseURL + "queryPrinterStatus"
	request := &QueryPrinterStatusRequest{
		RestRequest: a.GenerateRestRequest(),
		Sn:          sn,
	}
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return PrinterStateError, errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return PrinterStateError, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	if resp.Content.Data != nil && resp.Content.Data.(float64) >= 0 {
		return resp.Content.Data, nil
	}
	return PrinterStateError, nil
}

//11.批量获取指定打印机状态
func (a *API) QueryPrintersStatus(request *QueryPrintersStatusRequest) ([]float64, error) {
	url := baseURL + "queryPrintersStatus"
	request.RestRequest = a.GenerateRestRequest()
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return nil, errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return nil, fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	retVal := []float64{}
	if resp.Content.Data != nil && resp.Content.Data.(float64) >= 0 {
		for _, v := range resp.Content.Data.([]interface{}) {
			retVal = append(retVal, v.(float64))
		}
	}
	return nil, nil
}

//12.金额播报
func (a *API) PlayVoice(request *PlayVoiceRequest) error {
	url := baseURL + "playVoice"
	request.RestRequest = a.GenerateRestRequest()
	resp := xpyunPostJson(url, request)
	if resp.HttpStatusCode != HttpStatusSuccessCode {
		return errors.New("HTTP请求错误，请检查重试")
	}
	if resp.Content.Code != ResponseCodeSuccess {
		return fmt.Errorf("%v", XpuErrMsg2[resp.Content.Msg])
	}
	return nil
}
