package jxprintapi

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

const (
	prodURL    = "http://api.jxc4.com/openapi/CallOpenAPI"      // 老版本的URL
	prodURLNew = "http://print.jxcs.net/v2/openapi/CallOpenAPI" // 新版本的URL
	signKey    = "sign"
)
const (
	// ResponseCodeSuccess 操作成功
	ResponseCodeSuccess = 0
)

const (
	PrinterStatusStrOffline        = "离线。"
	PrinterStatusStrOnlineOK       = "在线，工作状态正常。"
	PrinterStatusStrOnlineAbnormal = "在线，工作状态不正常。"

	PrinterStatusUnknown        = 0
	PrinterStatusOffline        = -1
	PrinterStatusOnlineOK       = 1
	PrinterStatusOnlineAbnormal = 2
)

var (
	printStatusMap = map[string]int{
		PrinterStatusStrOffline:        PrinterStatusOffline,
		PrinterStatusStrOnlineOK:       PrinterStatusOnlineOK,
		PrinterStatusStrOnlineAbnormal: PrinterStatusOnlineAbnormal,
	}
)

type API struct {
	platformapi.APICookie

	appID  string
	appKey string
	client *http.Client
	config *platformapi.APIConfig
}

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

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

func (a *API) AccessAPI(apiName string, apiParams map[string]interface{}) (retVal map[string]interface{}, err error) {
	params := utils.MergeMaps(map[string]interface{}{
		"app_id": a.appID,
		"method": apiName,
	}, apiParams)

	err = platformapi.AccessPlatformAPIWithRetry(a.client,
		func() *http.Request {
			params["timestamp"] = utils.Int64ToStr(time.Now().Unix())
			sign := a.signParams(params)
			params[signKey] = sign
			fullURL := prodURLNew
			request, _ := http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
			request.Header.Set("charset", "UTF-8")
			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["code"], ResponseCodeSuccess))
			if code == ResponseCodeSuccess {
				retVal = jsonResult1
				return platformapi.ErrLevelSuccess, nil
			}
			newErr := utils.NewErrorIntCode(jsonResult1["desc"].(string), code)
			return platformapi.ErrLevelCodeIsNotOK, newErr
		})
	return retVal, err
}

type AddPrinterParam struct {
	PrintNo string `json:"print_no"` //打印机编号
	Name    string `json:"name"`     //打印机备注名
	SIM     string `json:"sim"`      //sim卡号-电话号码,接受验证的电话
	StoreId int64  `json:"store_id"` // 门店id
}

func (a *API) AddPrinter(addPrinterParams []*AddPrinterParam) (err error) {
	data, _ := json.Marshal(addPrinterParams)
	_, err = a.AccessAPI("AddPrinter", map[string]interface{}{
		"prints": string(data),
	})
	return err
}

func (a *API) DelPrinter(printNos []string, storeId string) (err error) {
	data, _ := json.Marshal(printNos)
	_, err = a.AccessAPI("DelPrinter", map[string]interface{}{
		"print_nos": string(data),
		"storeId":   storeId,
	})
	return err
}

type UpdatePrinterParam struct {
	PrintNo string `json:"print_no"`       //打印机编号
	Name    string `json:"name,omitempty"` //打印机备注名
	//SIM     string `json:"sim,omitempty"`  //sim卡号
	Sound  string `json:"sound,omitempty"`
	Volume int    `json:"volume,omitempty"`
}

func (a *API) UpdatePrinter(updatePrinterParam *UpdatePrinterParam) (err error) {
	_, err = a.AccessAPI("UpdatePrinter", utils.Struct2FlatMap(updatePrinterParam))
	return err
}

func (a *API) DelPrinterSeq(printNo string) (err error) {
	_, err = a.AccessAPI("DelPrinterSeq", map[string]interface{}{
		"print_no": printNo,
	})
	return err
}

type GetPrintMsgResult struct {
	MsgID   string `json:"msg_id"`
	PrintNo string `json:"print_no"`
	OrderNo int    `json:"order_no"`
	Content string `json:"content"`
	Status  int    `json:"status"`
	Comment string `json:"comment"`
}

func (a *API) GetPrintMsg(msgID string) (getPrintMsgResult *GetPrintMsgResult, err error) {
	result, err := a.AccessAPI("GetPrintMsg", map[string]interface{}{
		"msg_id": msgID,
	})
	if err == nil {
		utils.Map2StructByJson(result["data"].(map[string]interface{}), &getPrintMsgResult, false)
	}
	return getPrintMsgResult, err
}

func (a *API) GetPrinterStatus(printNo string) (status int64, err error) {
	result, err := a.AccessAPI("GetPrinterStatus", map[string]interface{}{
		"print_no": printNo,
	})
	if err == nil {
		status = utils.Interface2Int64WithDefault(result["data"], 0)
	}
	return status, err
}

func (a *API) DoPrint(printNo, content string, orderNo int) (msgID string, err error) {
	content = utils.FilterMb4(content)
	result, err := a.AccessAPI("DoPrint", map[string]interface{}{
		"print_no": printNo,
		"content":  content,
		"order_no": orderNo,
	})
	if err == nil {
		msgID = result["data"].(string)
	}
	return msgID, err
}

func (a *API) GetPrintList(printNo, printKey string, status, isOnline int, page, size int) ([]*PrintList, int64, error) {
	result, err := a.AccessAPI("QueryPrintList", map[string]interface{}{
		"print_no":  printNo,
		"print_key": printKey,
		"status":    status,
		"is_online": isOnline,
		"page":      page,
		"size":      size,
	})
	if err != nil {
		return nil, 0, err
	}
	list := result["data"].(map[string]interface{})
	printList := make([]*PrintList, 0, 0)
	byteDate, err := json.Marshal(list["printList"].([]interface{}))
	if err != nil {
		return nil, 0, err
	}
	if err = json.Unmarshal(byteDate, &printList); err != nil {
		return nil, 0, err
	}

	return printList, utils.MustInterface2Int64(list["count"]), nil
}

type PrintList struct {
	ID           int    `orm:"column(id)" json:"id"`
	CreatedAt    string `orm:"auto_now_add;type(datetime)" json:"createdAt"`
	UpdatedAt    string `orm:"auto_now;type(datetime)" json:"updatedAt"`
	DeletedAt    string `orm:"type(datetime);null" json:"deletedAt"`
	LastOperator string `orm:"size(32)" json:"lastOperator"`             // 最后操作员
	AppID        int    `orm:"column(app_id)" json:"app_id" db:"app_id"` //应用编号
	PrintNo      string `json:"print_no" db:"print_no"`                  //打印机编号
	PrintKey     string `json:"print_key" db:"print_key"`                //打印机识别码
	Name         string `json:"name" db:"name"`                          //打印机备注名
	Status       int    `json:"status" db:"status"`                      //打印机状态
	IsOnline     int    `json:"is_online" db:"is_online"`                //1在线，0离线
	IccID        string `orm:"column(icc_id)" json:"iccid" db:"icc_id"`  //sim卡号
	Sound        string `json:"sound" db:"sound"`                        //声音类型 sounda ,b,c,d,e,f,g
	Volume       int    `json:"volume" db:"volume"`                      //音量，1-5 ，对应打印机2-10
	FlowFlag     int    `json:"flowFlag" db:"flow_flag"`                 //是否超流量了，1表示超了
	OfflineCount int    `json:"offlineCount" db:"offline_count"`         //掉线次数
	UserId       string `json:"user_id" db:"user_id"`                    //打印机所属用户
}
