package trenditapi

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"git.rosy.net.cn/baseapi/platformapi"
	"git.rosy.net.cn/baseapi/utils"
	"io/ioutil"
	r "math/rand"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
	"unicode"
)

type API struct {
	locker      sync.RWMutex
	accessToken string

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

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

//生成BaseReq
func (a *API) GenBaseReq(bizParams interface{}) *BaseReq {
	//生成通用参数
	uid := utils.Time2Str(time.Now()) + RandString()
	timestamp := utils.Int64ToStr(time.Now().Unix())
	return &BaseReq{
		AppID: a.appID,
		Uid:   uid,
		STime: timestamp,
		Sign:  a.sign(uid, timestamp, "bizParams"),
	}
}

//生成随机字符串
func RandString() string {
	bytes := make([]byte, 16)
	for i := 0; i < 16; i++ {
		b := r.Intn(26) + 65
		bytes[i] = byte(b)
	}
	return string(bytes)
}

func (a *API) sign(uid, timestamp string, param string) (sign string) {
	aa := uid + a.appID + timestamp + a.appSecret + param
	return fmt.Sprintf("%x", md5.Sum([]byte(aa)))
}

func (a *API) HttpPostJson(url string, data interface{}) (*TIResponse, error) {
	//序列化参数
	b, err := json.Marshal(&data)
	if err != nil {
		var msg = fmt.Sprintf("json serialize err:%+v", err)
		fmt.Println(msg)
		result := TIResponse{
			HttpStatusCode: 500,
		}
		return &result, nil
	}

	fullUrl := utils.GenerateGetURL(BaseUrl, url, nil)

	request, err := http.NewRequest(http.MethodPost, fullUrl, strings.NewReader(string(b)))
	client := &http.Client{}
	timestamp := utils.Int64ToStr(time.Now().Unix())
	uid := timestamp + RandString()
	sign := a.sign(uid, timestamp, string(b))

	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	request.Header.Set("appid", a.appID)
	request.Header.Set("uid", uid)
	request.Header.Set("stime", timestamp)
	request.Header.Set("sign", sign)

	resp, err := client.Do(request)
	//resp, err := http.Post(utils.GenerateGetURL(BaseUrl, url, nil), "application/json;charset=UTF-8", bytes.NewBuffer(b))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	result := TIResponse{
		HttpStatusCode: resp.StatusCode,
	}

	var content BaseResp
	err = json.Unmarshal(body, &content)
	if err == nil {
		result.BaseRes = &content
	} else {
		return nil, err
	}

	return &result, nil
}

func StrRepeat(str string, repeatTimes int) string {
	return strings.Repeat(str, repeatTimes)
}

func CalcAsciiLenForPrint(data string) int {
	return len(data)
}

func FormatPrintOrderItemBig(foodName string, quantity int, price float64) string {
	orderNameEmpty := StrRepeat(" ", 8)
	quantityStr := strconv.Itoa(quantity)
	temprice := price / 100
	priceStr := fmt.Sprintf("%.2f", temprice)
	subtotalStr := fmt.Sprintf("%.2f", utils.Int2Float64(quantity)*temprice)
	result := `<font# bolder=1 height=2 width=1>` + foodName + "</font#><BR>"
	result += `<font# bolder=1 height=2 width=1>` + orderNameEmpty + "x" + quantityStr + `</font#><font# bolder=0 height=1 width=1>     </font#>`
	result += `<font# bolder=1 height=2 width=1>` + "￥" + priceStr + `</font#><font# bolder=0 height=1 width=1>   </font#>`
	result += `<font# bolder=1 height=2 width=1>` + "￥" + subtotalStr + `</font#>`
	//result += "<BR>"
	return result
}

func FormatPrintOrderItem(foodName string, quantity int, price float64) string {
	orderNameEmpty := StrRepeat(" ", 8)
	quantityStr := strconv.Itoa(quantity)
	temprice := price / 100
	priceStr := fmt.Sprintf("%.2f", temprice)
	subtotalStr := fmt.Sprintf("%.2f", utils.Int2Float64(quantity)*temprice)
	result := foodName + "<BR>"
	result += orderNameEmpty + "x" + quantityStr + `<font# bolder=0 height=1 width=1>     </font#>`
	result += "￥" + priceStr + `<font# bolder=0 height=1 width=1>   </font#>`
	result += "￥" + subtotalStr
	result += "<BR>"
	return result
}

const (
	ROW_MAX_CHAR_LEN           = 34
	LAST_ROW_MAX_NAME_CHAR_LEN = 16
	MAX_NAME_CHAR_LEN          = 16
	MaxLineLength              = 30
	LineLength                 = 32
	NewLineLength              = 28
)

//不带单价版本
func FormatPrintOrderItemV2(foodName string, quantity, cnt int) string {
	var (
		result  = ""
		restLen int
	)
	quantityStr := strconv.Itoa(quantity)
	foodNameLen := CalWidth(foodName) + 3
	if foodNameLen >= MaxLineLength {
		if n := foodNameLen / LineLength; n > 0 {
			restLen = foodNameLen % LineLength
		} else {
			restLen = foodNameLen - LineLength
		}
		repeatTimes := MaxLineLength - restLen
		if repeatTimes < 0 {
			repeatTimes = MaxLineLength
		}
		result += `<font# bolder=0 height=2 width=1>` + utils.Int2Str(cnt) + `.` + foodName
		result += StrRepeat(" ", repeatTimes) + `x` + quantityStr + `</font#>`
	} else {
		result += `<font# bolder=0 height=2 width=1>` + utils.Int2Str(cnt) + `.` + foodName + StrRepeat(" ", MaxLineLength-foodNameLen) + `x` + quantityStr + `</font#>`
	}
	result += "<BR>"
	fmt.Println(result)
	return result
}

func FormatPrintOrderItemBigV2(foodName string, quantity, cnt int) string {
	var (
		result  = ""
		restLen int
	)
	quantityStr := strconv.Itoa(quantity)
	foodNameLen := CalWidth(foodName) + 3
	if foodNameLen >= MaxLineLength {
		if n := foodNameLen / LineLength; n > 0 {
			restLen = foodNameLen % LineLength
		} else {
			restLen = foodNameLen - LineLength
		}
		result += `<font# bolder=1 height=2 width=1>` + utils.Int2Str(cnt) + `.` + foodName
		result += StrRepeat(" ", MaxLineLength-restLen) + `x` + quantityStr + `</font#>`
	} else {
		result += `<font# bolder=1 height=2 width=1>` + utils.Int2Str(cnt) + `.` + foodName + StrRepeat(" ", MaxLineLength-foodNameLen) + `x` + quantityStr + `</font#>`
	}
	result += "<BR>"
	fmt.Println(result)
	return result
}

//正则计算宽度
func CalWidth(str string) int {
	hzc := 0
	for _, v := range str {
		if unicode.Is(unicode.Han, v) {
			hzc++
		}
	}
	updateStr := regexp.MustCompile("[\u4e00-\u9fa5]{1,}").ReplaceAllString(str, "")
	l := len(updateStr)
	fmt.Println(hzc)
	ans := 2*hzc + l
	return ans
}
