package ebaiapi

import (
	"fmt"
	"regexp"
	"strings"

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

const (
	SkuStatusOnline  = 1 // 为上架
	SkuStatusOffline = 0 // 为下架
	SkuStatusDeleted = 2 // 为删除
)

const (
	UPCTypeStandard = 1
	UPCTypePrivate  = 0
)
const (
	MaxLeftNum          = 99999
	MaxSkuNameByteCount = 100 // skuname的最大字节数，注意不是字符数，超长饿百会报错：{"data":"","errno":20200,"error":"invalid param:[name]...

	MaxStoreSkuBatchSize = 100    // sku.offline, sku.online, sku.price.update.batch和sku.stock.update.batch这些批量操作的最大值
	MaxSkuCatRank        = 100000 // 商品排序优先级 ，最小值为1，最大值为100000，rank值较大的优先展示
	MaxCatCatRank        = 100000 // 自定义分类排序优先级 ，最小值为1，最大值为100000，rank值较大的优先展示
	MaxSkuListPageSize   = 100    //获取数量,1-100,默认20

	MaxCategoryNameLen = 12 // 商家分类名最大长度
)

var (
	shopSkuBatchFailedSkuReg = regexp.MustCompile(`请核查以下sku：(\{.*\})`)

	skuExistMsgList    = []string{"商品已存在", "shop sku exist", "已被使用，请更换"}
	skuNotExistMsgList = []string{"sku_id与shop_id不匹配", "SKU不存在或者已经被删除", "商品不存在"}
)

type CategoryInfo struct {
	CategoryID int64           `json:"category_id"`
	Name       string          `json:"name"`
	Rank       int             `json:"rank"` // 店内分类独有
	Children   []*CategoryInfo `json:"children"`
	Level      int             `json:"level"`
}

type SkuListParams struct {
	Page        int    `json:"page,omitempty"`
	PageSize    int    `json:"pagesize,omitempty"`
	Upc         string `json:"upc,omitempty"`
	SkuID       int64  `json:"sku_id,omitempty"`
	CustomSkuID string `json:"custom_sku_id,omitempty"`
	//UpcType     int    `json:"upc_type,omitempty"`
	GetUncate   int `json:"get_uncate,omitempty"`
	Delete      int `json:"delete,omitempty"`
	Enabled     int `json:"enabled,omitempty"`
	StartTime   int `json:"start_time,omitempty"`
	EndTime     int `json:"end_time,omitempty"`
	SkuIdOffset int `json:"sku_id_offset,omitempty"`
}

type SkuPhotoInfo struct {
	IsMaster int    `json:"is_master"`
	URL      string `json:"url"`
}

type SkuCustomCatInfo struct {
	CustomCatID   string `json:"custom_cat_id"`
	CustomCatName string `json:"custom_cat_name"`
}

type SkuInfo struct {
	CateId           int    `json:"cate_id"`
	CateId1          int    `json:"cate_id1"`
	CateId2          int    `json:"cate_id2"`
	CateName         string `json:"cate_name"`
	CateName1        string `json:"cate_name1"`
	CateName2        string `json:"cate_name2"`
	CustomCatIds     string `json:"custom_cat_ids"`
	CustomSkuId      string `json:"custom_sku_id"`
	DurationSaleFlag bool   `json:"duration_sale_flag"`
	IsInActivity     int    `json:"is_in_activity"`
	ItemId           int64  `json:"item_id"`
	LeftNum          int    `json:"left_num"`
	MarketPrice      int    `json:"market_price"`
	Minimum          int    `json:"minimum"`
	Name             string `json:"name"`
	NeedIce          string `json:"need_ice"`
	PackageFlag      bool   `json:"package_flag"`
	Photos           []struct {
		IsMaster int    `json:"is_master"`
		Url      string `json:"url"`
	} `json:"photos"`
	PreminusWeight    int           `json:"preminus_weight"`
	PreparationTime   int           `json:"preparation_time"`
	PrescriptionType  string        `json:"prescription_type"`
	ProcessDetail     []interface{} `json:"process_detail"`
	ProcessType       int           `json:"process_type"`
	ProductionAddr1   string        `json:"production_addr1"`
	ProductionAddr2   string        `json:"production_addr2"`
	ProductionAddr3   string        `json:"production_addr3"`
	Rtf               string        `json:"rtf"`
	SalePrice         int           `json:"sale_price"`
	SaleStep          int           `json:"sale_step"`
	SaleUnit          string        `json:"sale_unit"`
	Desc              string        `json:"desc"`
	SevenDaysNoReason bool          `json:"seven_days_no_reason"`
	SkuId             int64         `json:"sku_id"`
	SkuProperty       []interface{} `json:"sku_property"`
	Status            string        `json:"status"`
	Summary           string        `json:"summary"`
	Upc               string        `json:"upc"`
	UpcType           int           `json:"upc_type"`
	Weight            string        `json:"weight"`
	WeightFlag        int           `json:"weight_flag"`

	CustomCatIDs  string              `json:"custom_cat_ids"`
	CustomCatList []*SkuCustomCatInfo `json:"custom_cat_list"`
	CustomSkuID   string              `json:"custom_sku_id"`
	ShelfNumber   string              `json:"shelf_number"`
	UpdateTime    string              `json:"update_time"`
}

type PageDataInfo struct {
	Total       int        `json:"Total"`
	Page        int        `json:"Page"`
	Pages       int        `json:"Pages"`
	SkuIdOffset int        `json:"sku_id_offset"`
	List        []*SkuInfo `json:"List"`
}

type BatchOpSkuResult struct {
	SkuID    int64  `json:"sku_id"`
	Price    int    `json:"price,omitempty"`
	ErrorNo  int    `json:"error_no,omitempty"`
	ErrorMsg string `json:"error_msg,omitempty"`
}

type BatchOpResult struct {
	FailedList  []*BatchOpSkuResult `json:"failed_list"`
	SuccessList []*BatchOpSkuResult `json:"success_list"`
}

const (
	SkuIDTypeUnknown     = 0
	SkuIDTypeSkuID       = 1
	SkuIDTypeCustomSkuID = 2
	SkuIDTypeUpc         = 3
)

var (
	priceUpdateKeyIDMap = map[int]string{
		SkuIDTypeSkuID:       "skuid_price",
		SkuIDTypeCustomSkuID: "custom_sku_id",
		SkuIDTypeUpc:         "upc_price",
	}
	stockUpdateKeyIDMap = map[int]string{
		SkuIDTypeSkuID:       "skuid_stocks",
		SkuIDTypeCustomSkuID: "custom_sku_id",
		SkuIDTypeUpc:         "upc_stocks",
	}
)

type ShopSkuInfo struct {
	SkuID       int64
	CustomSkuID string
	Upc         string

	SalePrice   int64
	MarketPrice int64
	Stock       int
}

type ShopSkuInfoList []*ShopSkuInfo

func (v *ShopSkuInfo) GuessIDType() int {
	if v.SkuID > 0 {
		return SkuIDTypeSkuID
	} else if v.CustomSkuID != "" {
		return SkuIDTypeCustomSkuID
	}
	return SkuIDTypeUpc
}

func (v *ShopSkuInfo) ToSkuID(skuIDType int) (str string) {
	if skuIDType == SkuIDTypeUnknown {
		skuIDType = v.GuessIDType()
	}
	if skuIDType == SkuIDTypeSkuID {
		str = utils.Int64ToStr(v.SkuID)
	} else if skuIDType == SkuIDTypeCustomSkuID {
		str = v.CustomSkuID
	} else {
		str = v.Upc
	}
	return str
}

func (v *ShopSkuInfo) PriceString(skuIDType int) (str string) {
	str = v.ToSkuID(skuIDType) + ":" + utils.Int64ToStr(v.SalePrice)
	if v.MarketPrice > 0 {
		str += "," + utils.Int64ToStr(v.MarketPrice)
	}
	return str
}

func (v *ShopSkuInfo) StockString(skuIDType int) (str string) {
	str = v.ToSkuID(skuIDType) + ":" + utils.Int2Str(v.Stock)
	return str
}

func (l ShopSkuInfoList) PriceString(skuIDType int) (str string) {
	if len(l) > 0 {
		strList := make([]string, len(l))
		for k, v := range l {
			strList[k] = v.PriceString(skuIDType)
		}
		str = strings.Join(strList, ";")
	}
	return str
}

func (l ShopSkuInfoList) StockString(skuIDType int) (str string) {
	if len(l) > 0 {
		strList := make([]string, len(l))
		for k, v := range l {
			strList[k] = v.StockString(skuIDType)
		}
		str = strings.Join(strList, ";")
	}
	return str
}

func genSkuIDParams(skuIDstr string, customSkuID, upc string) map[string]interface{} {
	params := map[string]interface{}{}
	if skuIDstr != "" {
		params[KeySkuID] = skuIDstr
	} else if customSkuID != "" {
		params[KeyCustomSkuID] = customSkuID
	} else if upc != "" {
		params[KeyUPC] = upc
	} else {
		panic("skuID, customSkuID and upc are all no value!")
	}
	return params
}

// category相关的函数，shop_custom_id可重
func (a *API) ShopCategoryCreate(shopID string, parentID int64, name string, rank int) (catID int64, err error) {
	result, err := a.AccessAPI("sku.shop.category.create", map[string]interface{}{
		KeyShopID:            shopID,
		"parent_category_id": parentID,
		"name":               name,
		"rank":               rank,
	})
	if err == nil {
		if result.Data != nil {
			return utils.Interface2Int64WithDefault((result.Data.(map[string]interface{})["category_id"]), 0), nil
		}
	}
	if err != nil && strings.Contains(err.Error(), "新增的店内分类已存在") {
		errStr := err.Error()
		startIndex := strings.Index(errStr, "（")
		endIndex := strings.Index(errStr, "）")
		return utils.Str2Int64(errStr[startIndex+3 : endIndex]), nil
	}
	return 0, err
}

func (a *API) ShopCategoryGet(shopID string) (cats []*CategoryInfo, err error) {
	result, err := a.AccessAPI("sku.shop.category.get", utils.Params2Map(KeyShopID, shopID))
	if err == nil {
		if inMap, ok := result.Data.(map[string]interface{}); ok {
			cats := interface2CatList(inMap["categorys"], 1)
			return cats, nil
		}
	}
	return nil, err
}

func (a *API) ShopCategoryUpdate(shopID string, categoryID int64, name string, rank int) (err error) {
	_, err = a.AccessAPI("sku.shop.category.update", map[string]interface{}{
		KeyShopID:     shopID,
		"category_id": categoryID,
		"name":        name,
		"rank":        rank,
	})
	return err
}

// 饿百的商家分类是标签的概念，不管有没有商品在使用都可以删除，且有子分类的也可以直接删除（子分类也相应一并级连被删除）
func (a *API) ShopCategoryDelete(shopID string, categoryID int64) (err error) {
	_, err = a.AccessAPI("sku.shop.category.delete", map[string]interface{}{
		KeyShopID:     shopID,
		"category_id": categoryID,
	})
	return err
}

func (a *API) SkuGetItemsByCategoryId(shopID string, categoryID int64) (skus []map[string]interface{}, err error) {
	result, err := a.AccessAPI("sku.getItemsByCategoryId", map[string]interface{}{
		KeyShopID:     shopID,
		"category_id": categoryID,
	})
	if err == nil {
		return utils.Slice2MapSlice(result.Data.([]interface{})), nil
	}
	return nil, err
}

// 此函数查不到结果是不会报错的
func (a *API) SkuList(shopID string, params *SkuListParams) (skuInfo *PageDataInfo, err error) {
	params.PageSize = 100
	paramMap := utils.Struct2FlatMap(params)
	paramMap[KeyShopID] = shopID
	paramMap["include_cate_info"] = 1
	result, err := a.AccessAPI("sku.list", paramMap)
	if err == nil {
		err = utils.Map2StructByJson(result.Data, &skuInfo, true)
	}
	return skuInfo, err
}

// 饿百商品名可以相同，不会报错
func (a *API) SkuCreate(trackInfo, shopID string, customSkuID string, params map[string]interface{}) (skuID int64, err error) {
	defParams := map[string]interface{}{
		KeyShopID:      shopID,
		KeyCustomSkuID: customSkuID,
	}
	if utils.IsNil(params["upc"]) {
		params["upc"] = "upc-" + customSkuID
	}
	/*if params["brand_id"] == nil {
		defParams["brand_id"] = 0
	}
	if params["brand_name"] == nil {
		defParams["brand_name"] = "无" // 很狗血的是，你还必须填个无才行。。。
	}*/
	params = utils.MergeMaps(params, defParams)
	result, err := a.AccessAPI2("sku.create", params, trackInfo)
	if err == nil && result.Data != nil {
		return utils.Interface2Int64WithDefault(result.Data.(map[string]interface{})[KeySkuID], 0), nil
	} else if err != nil && strings.Contains(err.Error(), "商品已存在") {
		skuIDStr := err.Error()
		start := strings.LastIndex(skuIDStr, "sku_id")
		end := strings.Index(skuIDStr, "level")
		return utils.Str2Int64(skuIDStr[start+7 : end-1]), nil
	}

	return 0, err
}

// 饿百商品名可以相同，不会报错 SkuCreate2 customSkuID改为string
func (a *API) SkuCreate2(trackInfo, shopID string, customSkuID string, params map[string]interface{}) (skuID int64, err error) {
	defParams := map[string]interface{}{
		KeyShopID:      shopID,
		KeyCustomSkuID: customSkuID,
	}
	if utils.IsNil(params["upc"]) {
		params["upc"] = "upc-" + customSkuID
	}
	/*if params["brand_id"] == nil {
		defParams["brand_id"] = 0
	}
	if params["brand_name"] == nil {
		defParams["brand_name"] = "无" // 很狗血的是，你还必须填个无才行。。。
	}*/
	params = utils.MergeMaps(params, defParams)
	result, err := a.AccessAPI2("sku.create", params, trackInfo)
	if err == nil && result.Data != nil {
		return utils.Interface2Int64WithDefault(result.Data.(map[string]interface{})[KeySkuID], 0), nil
	} else if err != nil && strings.Contains(err.Error(), "商品已存在") {
		skuIDStr := err.Error()
		start := strings.LastIndex(skuIDStr, "sku_id")
		end := strings.Index(skuIDStr, "level")
		return utils.Str2Int64(skuIDStr[start+7 : end-1]), nil
	}

	return 0, err
}

func (a *API) SkuUpdate(trackInfo, shopID string, ebaiSkuID int64, params map[string]interface{}) (skuID int64, err error) {
	defParams := map[string]interface{}{
		KeyShopID: shopID,
		KeySkuID:  ebaiSkuID,
	}
	result, err := a.AccessAPI2("sku.update", utils.MergeMaps(params, defParams), trackInfo)
	if err == nil {
		return utils.Interface2Int64WithDefault(result.Data.(map[string]interface{})[KeySkuID], 0), nil
	}
	return 0, err
}

func intIDs2Str(intIDs []int64) (str string) {
	return strings.Join(utils.Int64Slice2String(intIDs), ",")
}

func strIDs2Str(strIDs []string) (str string) {
	return strings.Join(strIDs, ",")
}

// 之前的处理方法
func handleShopSkuBatchResult(result *ResponseResult) (opResult *BatchOpResult, err error) {
	if dataStr, ok := result.Data.(string); ok && dataStr != "" {
		matchList := shopSkuBatchFailedSkuReg.FindStringSubmatch(dataStr)
		if len(matchList) == 2 {
			var failedMap map[string]interface{}
			if err = utils.UnmarshalUseNumber([]byte(dataStr), &failedMap); err == nil && len(failedMap) > 0 {
				opResult = &BatchOpResult{}
				for _, v := range failedMap {
					var skuID int64
					if vStr, ok := v.(string); ok {
						skuID = utils.Str2Int64WithDefault(vStr, 0)
					} else {
						skuID = utils.Interface2Int64WithDefault(v, 0)
					}
					opResult.FailedList = append(opResult.FailedList, &BatchOpSkuResult{
						SkuID: skuID,
					})
				}
			}
		}
	}
	return opResult, err
}

func handleShopSkuBatchErr(err error) (opResult *BatchOpResult, outErr error) {
	outErr = err
	if errExt, ok := err.(*utils.ErrorWithCode); ok {
		if errExt.ErrMsg() != "" {
			var data interface{}
			if err2 := utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &data); err2 == nil {
				if err2 = utils.Map2StructByJson(data, &opResult, true); err2 == nil {
					// 将以\u表示的字符串标准化，并去掉成功的
					errExt.SetErrMsg(string(utils.MustMarshal(opResult.FailedList)))
					outErr = errExt
				}
			}
		}
	}
	return opResult, outErr
}

// 门店商品批量修改可售，价格，库存的API,在2019/07/26之前，除了SkuPriceUpdateBatch外，其它API在部分失败时会返回成功，
// 失败信息在data中，但2019/07/26之后，行为与SkuPriceUpdateBatch一致了，即完全成功时，返回成功，没有失败成功明细，
// 部分失败时，返回失败，详情在error中，
// 另外需要注意的是SkuPriceUpdateBatch的失败明细中的skuID是int64，但其它几个是string...

// 文档上说支持custom_sku_id，但实际好像只支持skuid
// 饿百删除商品后，还要等待5分钟后才会归档商品，才会真正删除生效
func (a *API) SkuDelete(trackInfo, shopID string, skuIDs []int64, customSkuDs []string) (opResult *BatchOpResult, err error) {
	params := genSkuIDParams(intIDs2Str(skuIDs), strIDs2Str(customSkuDs), "")
	params[KeyShopID] = shopID
	result, err := a.AccessAPI2("sku.delete", params, trackInfo)
	if err == nil {
		opResult, err = handleShopSkuBatchResult(result)
	} else {
		opResult, err = handleShopSkuBatchErr(err)
	}
	return opResult, err
}

func (a *API) SkuOnline(trackInfo, shopID string, skuIDs []int64, customSkuDs, upcs []string) (opResult *BatchOpResult, err error) {
	params := genSkuIDParams(intIDs2Str(skuIDs), strIDs2Str(customSkuDs), strIDs2Str(upcs))
	params[KeyShopID] = shopID
	result, err := a.AccessAPI2("sku.online", params, trackInfo)
	if err == nil {
		opResult, err = handleShopSkuBatchResult(result)
	} else {
		opResult, err = handleShopSkuBatchErr(err)
	}
	return opResult, err
}

func (a *API) SkuOnlineOne(trackInfo, shopID string, skuID int64, customSkuID, upc string) (err error) {
	params := genSkuIDParams(utils.Int64ToStrNoZero(skuID), customSkuID, upc)
	params[KeyShopID] = shopID
	_, err = a.AccessAPI2("sku.online.one", params, trackInfo)
	return err
}

func (a *API) SkuOffline(trackInfo, shopID string, skuIDs []int64, customSkuDs, upcs []string) (opResult *BatchOpResult, err error) {
	params := genSkuIDParams(intIDs2Str(skuIDs), strIDs2Str(customSkuDs), strIDs2Str(upcs))
	params[KeyShopID] = shopID
	result, err := a.AccessAPI2("sku.offline", params, trackInfo)
	if err == nil {
		opResult, err = handleShopSkuBatchResult(result)
	} else {
		opResult, err = handleShopSkuBatchErr(err)
	}
	return opResult, err
}

func (a *API) SkuOfflineOne(trackInfo, shopID string, skuID int64, customSkuID, upc string) (err error) {
	params := genSkuIDParams(utils.Int64ToStrNoZero(skuID), customSkuID, upc)
	params[KeyShopID] = shopID
	_, err = a.AccessAPI2("sku.offline.one", params, trackInfo)
	return err
}

func (a *API) SkuPriceUpdateBatch(trackInfo, shopID string, priceList ShopSkuInfoList, skuIDType int) (opResult *BatchOpResult, err error) {
	params := map[string]interface{}{
		KeyShopID:                      shopID,
		priceUpdateKeyIDMap[skuIDType]: priceList.PriceString(skuIDType),
	}
	result, err := a.AccessAPI2("sku.price.update.batch", params, trackInfo)
	if err == nil {
		opResult, err = handleShopSkuBatchResult(result)
	} else {
		opResult, err = handleShopSkuBatchErr(err)
	}
	return opResult, err
}

func (a *API) SkuPriceUpdateOne(trackInfo, shopID string, priceInfo *ShopSkuInfo) (opResult *BatchOpResult, err error) {
	skuIDType := priceInfo.GuessIDType()
	params := map[string]interface{}{
		KeyShopID:                      shopID,
		priceUpdateKeyIDMap[skuIDType]: priceInfo.PriceString(skuIDType),
	}
	_, err = a.AccessAPI2("sku.price.update.one", params, trackInfo)
	return opResult, err
}

func (a *API) SkuStockUpdateBatch(trackInfo, shopID string, stockList ShopSkuInfoList, skuIDType int) (opResult *BatchOpResult, err error) {
	params := map[string]interface{}{
		KeyShopID:                      shopID,
		stockUpdateKeyIDMap[skuIDType]: stockList.StockString(skuIDType),
	}
	result, err := a.AccessAPI2("sku.stock.update.batch", params, trackInfo)
	if err == nil {
		opResult, err = handleShopSkuBatchResult(result)
	} else {
		opResult, err = handleShopSkuBatchErr(err)
	}
	return opResult, err
}

func (a *API) SkuStockUpdateOne(trackInfo, shopID string, stockInfo *ShopSkuInfo) (err error) {
	skuIDType := stockInfo.GuessIDType()
	params := map[string]interface{}{
		KeyShopID:                      shopID,
		stockUpdateKeyIDMap[skuIDType]: stockInfo.StockString(skuIDType),
	}
	_, err = a.AccessAPI2("sku.stock.update.one", params, trackInfo)
	return err
}

func (a *API) SkuShopCategoryMap(shopID string, skuID int64, customSkuID string, categoryID int64, rank int) (err error) {
	params := map[string]interface{}{
		KeyShopID:     shopID,
		KeyCategoryID: categoryID,
	}
	if skuID > 0 {
		params[KeySkuID] = skuID
	} else {
		params[KeyCustomSkuID] = customSkuID
	}
	if rank > 0 {
		params["rank"] = rank
	}
	_, err = a.AccessAPI("sku.shop.category.map", params)
	return err
}

// 饿百的这个API有点怪，虽然有shopID参数，但返回的链接可以跨店使用
func (a *API) SkuUploadRTF(shopID, rtfDetail string) (rtfURL string, err error) {
	params := map[string]interface{}{
		KeyShopID:    shopID,
		"rtf_detail": rtfDetail,
	}
	result, err := a.AccessAPI("sku.uploadrtf", params)
	if err == nil {
		rtfURL = utils.Interface2String(result.Data.(map[string]interface{})["url"])
	}
	return rtfURL, err
}

func BuildRFTFromImgs(imgList ...string) string {
	imgList2 := make([]string, len(imgList))
	for index, img := range imgList {
		imgList2[index] = fmt.Sprintf(`<img align="absmiddle" src="%s"  alt="%s" />`, img, img)
	}
	return strings.Join(imgList2, "\n")
}

//
func interface2CatList(data interface{}, level int) (cats []*CategoryInfo) {
	maps, ok := data.([]interface{})
	if ok {
		cats = make([]*CategoryInfo, len(maps))
		for index, v := range maps {
			cats[index] = interface2Cat(v, level)
		}
	}
	return cats
}

func interface2Cat(data interface{}, level int) (cat *CategoryInfo) {
	catMap := data.(map[string]interface{})
	cat = &CategoryInfo{
		CategoryID: utils.MustInterface2Int64(catMap["category_id"]),
		Name:       utils.Interface2String(catMap["name"]),
		Rank:       int(utils.MustInterface2Int64(catMap["rank"])),
		Children:   interface2CatList(catMap["children"], level+1),
		Level:      level,
	}
	return cat
}

func IsErrCategoryExist(err error) (isExist bool) {
	return utils.IsErrMatch(err, "1", []string{"商户已存在该自定义分类"})
}

func IsErrCategoryNotExist(err error) (isNotExist bool) {
	return utils.IsErrMatch(err, "", []string{"不存在该自定义分类ID", "商户不存在该自定义分类"})
}

func IsErrSkuExist(err error) (isExist bool) {
	return utils.IsErrMatch(err, "1", skuExistMsgList)
}

func IsErrSkuNotExist(err error) (isExist bool) {
	return utils.IsErrMatch(err, "1", skuNotExistMsgList)
}

func IsMsgSkuExist(msg string) bool {
	return utils.IsErrMsgMatch(msg, skuExistMsgList)
}

func IsMsgSkuNotExist(msg string) bool {
	return utils.IsErrMsgMatch(msg, skuNotExistMsgList)
}

func (a *API) GetEbaiSkuIDFromCustomID(shopID, customSkuID string) (ebaiSkuID int64) {
	if skuInfo, err2 := a.SkuList(shopID, &SkuListParams{
		CustomSkuID: customSkuID,
	}); err2 == nil && skuInfo != nil && len(skuInfo.List) > 0 {
		ebaiSkuID = skuInfo.List[0].SkuId
	}
	return ebaiSkuID
}

func (a *API) GetEbaiCatIDFromName(shopID, catName string) (ebaiCatID int64) {
	if catList, err2 := a.ShopCategoryGet(shopID); err2 == nil {
		for _, v := range catList {
			if v.Name == catName {
				ebaiCatID = v.CategoryID
				break
			}
			for _, v2 := range v.Children {
				if v2.Name == catName {
					ebaiCatID = v2.CategoryID
					break
				}
			}
		}
	}
	return ebaiCatID
}

// CategoryAttrValueList 根据分类id获取商品属性
//https://open-retail.ele.me/#/apidoc/me.ele.retail:sku.category.property.list-3?aopApiCategory=item_cate&type=item_all
func (a *API) CategoryAttrValueList(cat3Id int64, shopId string) (categoryAttrValueListResult []*CategoryAttr, err error) {
	result, err := a.AccessAPI("sku.category.property.list", map[string]interface{}{
		"cat3_id": cat3Id,
		"shop_id": shopId,
	})
	if err == nil && result.ErrNo == 0 {
		err = utils.UnmarshalUseNumber(utils.MustMarshal(result.Data), &categoryAttrValueListResult)
	}
	return categoryAttrValueListResult, err
}

type CategoryAttr struct {
	PropertyId     int64           `json:"propertyId"`     // 属性ID
	CategoryId     int64           `json:"categoryId"`     // 所属叶子类目ID
	PropertyName   string          `json:"propertyName"`   // 属性名
	Required       bool            `json:"required"`       // 是否必选
	MultiSelect    bool            `json:"multiSelect"`    // 属性值是否多选
	EnumProp       bool            `json:"enumProp"`       // 是否枚举属性
	InputProp      bool            `json:"inputProp"`      // 是否可输入属性
	SaleProp       bool            `json:"saleProp"`       // 是否销售属性，销售属性只能用于生成多规格
	SortOrder      bool            `json:"sortOrder"`      // 排序值
	MajorProp      bool            `json:"majorProp"`      // 是否关键属性
	PropertyValues []PropertyValue `json:"propertyValues"` // 属性值列表
}
type PropertyValue struct {
	ValueId   int64  `json:"ValueId"`   // 属性值id
	ValueData string `json:"valueData"` // 属性值内容
	SortOrder int64  `json:"sortOrder"` // 排序码
}
