package aliupcapi

import (
	"fmt"
	"net/http"
	"regexp"
	"strings"

	"git.rosy.net.cn/baseapi/platformapi"
	"git.rosy.net.cn/baseapi/utils"
)

const (
	url         = "https://codequery.market.alicloudapi.com"
	url2        = "http://tiaoma.dxerp.net/api"
	successCode = "200"
)

var (
	regexpUpc  = regexp.MustCompile(`<span class='v'>(.*?)</span>`)
	skuNamePat = regexp.MustCompile(`([\(（\[【][^\(（\[【\)）\]】]*[\)）\]】])?(.*?)([(（].*[)）])?\s*约?([1-9][\d\.]*)(g|G|kg|kG|Kg|KG|l|L|ml|mL|Ml|ML|克)\s*([(（].*[)）])?\s*(?:\/|／|)\s*([^\s（）()]{0,2})\s*([（(].*[）)])?$`)
)

type API struct {
	appCode string
	client  *http.Client
	config  *platformapi.APIConfig
}

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

func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal map[string]interface{}, err error) {
	err = platformapi.AccessPlatformAPIWithRetry(a.client,
		func() *http.Request {
			request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(url, action, params), nil)
			request.Header.Set("Authorization", "APPCODE "+a.appCode)
			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")
			}
			if err == nil {
				if jsonResult1["status"] != successCode {
					errLevel = platformapi.ErrLevelGeneralFail
					errMsg := jsonResult1["msg"].(string)
					err = utils.NewErrorCode(errMsg, utils.Int64ToStr(utils.Interface2Int64WithDefault(jsonResult1["status"], 0)))
				}
				retVal = jsonResult1
			}
			return errLevel, err
		})
	return retVal, err
}

func (a *API) AccessAPI2(action string, params map[string]interface{}) (retVal map[string]interface{}, err error) {
	fullURL := utils.GenerateGetURL(url2, action, nil)
	err = platformapi.AccessPlatformAPIWithRetry(a.client,
		func() *http.Request {
			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")
			}
			if err == nil {
				if jsonResult1 == nil {
					errLevel = platformapi.ErrLevelGeneralFail
					errMsg := "未查询到数据！"
					err = utils.NewErrorCode(errMsg, "-1")
				}
				retVal = jsonResult1
			}
			return errLevel, err
		})
	return retVal, err
}

type GetAliUpcInfoResult struct {
	Code        string `json:"code"`
	GoodsName   string `json:"goodsName"`
	ManuName    string `json:"manuName"`
	ManuAddress string `json:"manuAddress"`
	Spec        string `json:"spec"`
	Price       string `json:"price"`
	Img         string `json:"img"`
	GoodsType   string `json:"goodsType"`
	Ycg         string `json:"ycg"`
	Trademark   string `json:"trademark"`
	Remark      string `json:"remark"`
}

func (a *API) GetAliUpcInfo(code string) (getAliUpcInfoResult *GetAliUpcInfoResult, err error) {
	result, err := a.AccessAPI("querybarcode", map[string]interface{}{
		"code": code,
	})
	if err == nil {
		utils.Map2StructByJson(result["result"], &getAliUpcInfoResult, false)
	}
	return getAliUpcInfoResult, err
}

type GetNetUpcInfoResult struct {
	Upc         string  `json:"upc"`
	Name        string  `json:"name"`
	SpecQuality float32 `json:"specQuality"`
	SpecUnit    string  `json:"specUnit"`
	Unit        string  `json:"unit"`
	Address     string  `json:"address"`
	Price       float64 `json:"price"`
}

func (a *API) GetNetUpcInfo(bar string) (getNetUpcInfo *GetNetUpcInfoResult, err error) {
	result, err := a.AccessAPI2("pubCommo.ashx", map[string]interface{}{
		"bar": bar,
		"k":   "tmppagequerysp",
	})
	if err == nil {
		getNetUpcInfo = &GetNetUpcInfoResult{}
		body := result["fakeData"].(string)
		if strings.Contains(body, "没有收录") {
			return getNetUpcInfo, err
		}
		results := regexpUpc.FindAllStringSubmatch(body, -1)
		getNetUpcInfo.Upc = results[0][1]
		getNetUpcInfo.Name = results[1][1]
		if results[2][1] != "" {
			specUnit, specQuality := SplitSkuName(results[2][1])
			getNetUpcInfo.SpecUnit = specUnit
			getNetUpcInfo.SpecQuality = specQuality
		}
		getNetUpcInfo.Unit = results[3][1]
		getNetUpcInfo.Address = results[4][1]
		getNetUpcInfo.Price = utils.Str2Float64(results[5][1])
		return getNetUpcInfo, err
	}
	return getNetUpcInfo, err
}

func SplitSkuName(skuName string) (specUnit string, specQuality float32) {
	searchResult := skuNamePat.FindStringSubmatch(skuName)
	if searchResult != nil {
		specUnit = strings.ToLower(strings.Replace(searchResult[5], "克", "g", -1))
		if specUnit == "l" {
			specUnit = "L"
		}
		specQuality = float32(utils.Str2Float64(searchResult[4]))
	}
	return specUnit, specQuality
}
