package mtwm

import (
	"encoding/json"
	"fmt"
	beego "github.com/astaxie/beego/server/web"
	"math"
	"regexp"
	"strings"

	"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
	"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/business/model/dao"
	"git.rosy.net.cn/jx-callback/business/partner"
	"git.rosy.net.cn/jx-callback/business/partner/putils"
	"git.rosy.net.cn/jx-callback/globals"
)

const (
	updateTypeStock = iota
	updateTypeStatus
	updateTypePrice
)

const (
	defVendorCatID = 200001903 // 生菜

	specialStoreID = "8171010"
	// specialStoreID = "2523687"
)

var (
	sensitiveWordRegexp = regexp.MustCompile(`包含敏感词：(\[.*\])`)
)

func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
	switch funcID {
	case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice:
		batchSize = mtwmapi.MaxStoreSkuBatchSize
	case partner.FuncDeleteStoreSkus:
		batchSize = mtwmapi.MaxBatchDeleteSize
	case partner.FuncCreateStoreSkus:
		batchSize = 1 // 可考虑用批量操作
	case partner.FuncUpdateStoreSkus:
		batchSize = 1 // mtwmapi.MaxStoreSkuBatchSize
	case partner.FuncGetStoreSkusFullInfo:
		batchSize = 1
	case partner.FuncCreateActs:
		batchSize = mtwmapi.MaxRetailDiscountCreateBatchSize
	case partner.FuncCancelActs:
		batchSize = mtwmapi.MaxRetailDiscountDeleteBatchSize
	}
	return batchSize
}

func getStoreVendorOrgCode(storeID int) (vendorOrgCode string) {
	if storeMap, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, ""); storeMap != nil {
		return storeMap.VendorOrgCode
	}
	return vendorOrgCode
}

// 门店分类
func (p *PurchaseHandler) GetStoreAllCategories(ctx *jxcontext.Context, storeID int, vendorStoreID string) (cats []*partner.BareCategoryInfo, err error) {
	remoteCats, err := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatList(vendorStoreID)
	if err == nil {
		cats = convertVendorCatList(remoteCats)
	}
	return cats, err
}

func convertVendorCatList(remoteCats []*mtwmapi.RetailCategoryInfo) (cats []*partner.BareCategoryInfo) {
	for _, rCat := range remoteCats {
		cat := &partner.BareCategoryInfo{
			VendorCatID: rCat.Code,
			Name:        rCat.Name,
			Level:       rCat.Level,
			Seq:         rCat.Sequence,
			Children:    convertVendorCatList(rCat.Children),
		}
		if cat.VendorCatID == "" {
			cat.VendorCatID = rCat.Name
		}
		cats = append(cats, cat)
	}
	return cats
}

func (p *PurchaseHandler) IsErrCategoryExist(err error) (isExist bool) {
	return mtwmapi.IsErrCategoryExist(err)
}

func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) {
	return mtwmapi.IsErrCategoryNotExist(err)
}

func catCode2Str(catCode int) (catCodeStr string) {
	if catCode > 0 {
		catCodeStr = utils.Int2Str(catCode)
	}
	return catCodeStr
}

func tryCatName2Code(originName string) (catCodeStr string) {
	if intValue := utils.Str2Int64WithDefault(originName, 0); intValue > 0 {
		catCodeStr = utils.Int64ToStr(intValue)
		if catCodeStr != originName {
			catCodeStr = ""
		}
	}
	return catCodeStr
}

func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
	level := 1
	if storeCat.ParentCatName != "" {
		level = 2
	}
	originName := ""
	catName := storeCat.Name
	catCode := storeCat.ID

	subCatName := ""
	subCatCode := 0
	if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 {
		// 修改一级分类
		originName = storeCat.VendorCatID
	}
	if level == 2 { // 二级分类
		// 创建二级分类
		originName = storeCat.ParentVendorCatID
		catName = storeCat.ParentCatName
		catCode = storeCat.ParentID
		subCatName = storeCat.Name
		subCatCode = storeCat.ID
		if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 {
			// 修改二级分类
			originName = storeCat.VendorCatID
			catName = storeCat.Name
			catCode = storeCat.ID
			subCatName = ""
			subCatCode = 0
		}
	}
	if catName == "" {
		panic("catName is empty")
	}
	catName = utils.FilterEmoji(catName)
	subCatName = utils.FilterEmoji(subCatName)
	if globals.EnableMtwmStoreWrite {
		param4Update := &mtwmapi.Param4UpdateCat{
			CategoryCodeOrigin:    tryCatName2Code(originName),
			CategoryNameOrigin:    originName,
			CategoryCode:          catCode2Str(catCode),
			SecondaryCategoryCode: catCode2Str(subCatCode),
			SecondaryCategoryName: subCatName,
			Sequence:              storeCat.Seq,
		}
		api := getAPI(storeCat.VendorOrgCode, storeID, vendorStoreID)
		err = api.RetailCatUpdate(vendorStoreID, catName, param4Update)
		if storeCat.CatSyncStatus&model.SyncFlagNewMask == 0 && p.IsErrCategoryNotExist(err) && originName != "" { // 修改分类名，但分类不存在
			storeCat.CatSyncStatus |= model.SyncFlagNewMask
			err = p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat)
		}

		// 门店内存在重复的分类：【柑桔柚类】 【底料】，请先删除重复分类后再操作。
		if err != nil && strings.Contains(err.Error(), "门店内存在重复的分类：") {
			for _, v := range deleteRepeatCat(err.Error()) {
				if len(v) > 0 {
					if err2 := api.RetailCatDelete(vendorStoreID, "", v, model.YES); err != nil {
						globals.SugarLogger.Errorf("RetailCatDelete delete err : [%v]", err2)
					}
				}
			}
		}
	}

	if err == nil {
		// storeCat.VendorCatID = utils.FilterEmoji(storeCat.Name)
		storeCat.VendorCatID = utils.Int2Str(storeCat.ID)
	}
	return err
}

// deleteRepeatCat 门店内存在重复的分类：【柑桔柚类】 【底料】 【火锅】，请先删除重复分类后再操作。
func deleteRepeatCat(param string) []string {
	firstIndex := strings.Index(param, "【")
	lastIndex := strings.LastIndex(param, "】")
	newParam := param[firstIndex:lastIndex]
	deleteCat := make([]string, 0, 0)
	for _, v := range strings.Split(newParam, "【") {
		if strings.TrimSpace(v) == "" {
			continue
		} else if strings.Contains(v, "【") {
			for _, v2 := range strings.Split(v, "【") {
				if strings.TrimSpace(v) == "" {
					continue
				}
				if strings.TrimSpace(v2) != "" {
					deleteCat = append(deleteCat, v2)
				}
			}
		} else if strings.Contains(v, "】") {
			for _, v3 := range strings.Split(v, "】") {
				if strings.TrimSpace(v3) == "" {
					continue
				}
				if strings.TrimSpace(v3) != "" {
					deleteCat = append(deleteCat, v3)
				}
			}
		} else {
			deleteCat = append(deleteCat, v)
		}
	}
	return deleteCat
}

func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
	return p.CreateStoreCategory(ctx, storeID, vendorStoreID, storeCat)
}

func (p *PurchaseHandler) DeleteStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID, vendorCatID string, level int) (err error) {
	if false {
		if globals.EnableMtwmStoreWrite {
			err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatDelete(vendorStoreID, tryCatName2Code(vendorCatID), vendorCatID, model.NO)
		}
	} else {
		var catCodes []string
		if catCode := tryCatName2Code(vendorCatID); catCode != "" {
			catCodes = []string{catCode}
		}
		if globals.EnableMtwmStoreWrite {
			if level == 1 {
				err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, catCodes, []string{vendorCatID}, nil, nil, nil)
			} else {
				err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, catCodes, []string{vendorCatID}, nil)
			}
		}
	}
	return err
}

// GetCategoryAttrList 根据末级类目id获取类目属性列表
func GetCategoryAttrList(appOrgCode string, tagID int) (categoryAttrListResult []*mtwmapi.CategoryAttrListResult, err error) {
	if resp, err := getAPI(appOrgCode, 0, "").CategoryAttrList(int64(tagID)); err == nil {
		return resp, nil
	}
	return nil, err
}

// GetMTProductRule 获取美团商品上传规则
func GetMTProductRule(tagID int) (categoryAttrListResult *mtwmapi.ProductRulesObj, err error) {
	if resp, err := getAPI(beego.AppConfig.DefaultString("mtwmAppID2", ""), 0, "").RetailProductRules(int64(tagID)); err == nil {
		return resp, nil
	}
	return nil, err
}

//GetCategoryAttrValueList 查询特殊属性的属性值列表
func GetCategoryAttrValueList(appOrgCode, keyword string, attrID int) (categoryAttrValueListResult []*mtwmapi.CategoryAttrValueListResult, err error) {
	if attrID != utils.Str2Int(mtwmapi.SpecialAttrBrand) && attrID != utils.Str2Int(mtwmapi.SpecialAttrProducer) || len(keyword) == 0 || len(appOrgCode) == 0 {
		return nil, nil
	}
	if resp, err := getAPI(appOrgCode, 0, "").CategoryAttrValueList(int64(attrID), keyword); err == nil {
		return resp, nil
	}
	return nil, nil
}

// GetRetailRecommendTag 根据商品UPC或名称或类目ID查询平台推荐类目及类目属性信息
func GetRetailRecommendTag(appOrgCode, appPoiCode, name string, tagID, tagType int) (*mtwmapi.RetailRecommendTagResp, error) {
	if resp, err := getAPI(appOrgCode, 0, appPoiCode).RetailRecommendTag(name, appPoiCode, tagID, tagType); err == nil {
		return resp, nil
	} else {
		return nil, err
	}
}

//批量更新商品进货价
func BatchSetRestockingPrice(ctx *jxcontext.Context, storeID int, vendorStoreID string, param []*mtwmapi.SpuData) error {
	if err := getAPI(getStoreVendorOrgCode(storeID), storeID, "").BatchSetRestockingPrice(ctx.GetTrackInfo(), vendorStoreID, param); err != nil {
		return err
	}
	return nil
}

// 门店商品

// 多门店平台不需要实现这个接口

func (p *PurchaseHandler) IsErrSkuExist(err error) (isExist bool) {
	return false
}

func (p *PurchaseHandler) IsErrSkuNotExist(err error) (isNotExist bool) {
	return mtwmapi.IsErrSkuNotExist(err)
}

// func duplicateStoreSkuList(storeSkuList []*dao.StoreSkuSyncInfo, index int) (newStoreSkuList []*dao.StoreSkuSyncInfo) {
// 	newStoreSkuList = make([]*dao.StoreSkuSyncInfo, len(storeSkuList))
// 	for k, v := range storeSkuList {
// 		tmp := *v
// 		tmp.SkuName = fmt.Sprintf("%s.%d", tmp.SkuName, index)
// 		tmp.SkuID = index*1000000 + tmp.SkuID
// 		newStoreSkuList[k] = &tmp
// 	}
// 	return newStoreSkuList
// }

func (p *PurchaseHandler) UpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, false)
	// if err == nil && vendorStoreID == specialStoreID {
	// 	for i := 0; i < 2; i++ {
	// 		p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true)
	// 	}
	// }
	return failedList, err
}

func (p *PurchaseHandler) CreateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	failedList, err = p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, storeSkuList, true)
	// if err == nil && vendorStoreID == specialStoreID {
	// 	for i := 0; i < 2; i++ {
	// 		p.createOrUpdateStoreSkus(ctx, storeID, vendorStoreID, duplicateStoreSkuList(storeSkuList, i+1), true)
	// 	}
	// }
	return failedList, err
}

// 对于多门店平台来说，storeSkuList中只有SkuID与VendorSkuID有意义
func (p *PurchaseHandler) createOrUpdateStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*dao.StoreSkuSyncInfo, isCreate bool) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	var syncType string
	foodDataList := make([]map[string]interface{}, len(storeSkuList))
	if isCreate {
		syncType = "创建商品"
	} else {
		syncType = "更新商品"
	}

	for i, storeSku := range storeSkuList {
		isNeedUpdatePrice := isCreate //storeSku.SkuSyncStatus&(model.SyncFlagPriceMask|model.SyncFlagNewMask) != 0
		foodData := make(map[string]interface{})
		foodDataList[i] = foodData
		foodData[mtwmapi.KeyAppFoodCode] = utils.Int2Str(storeSku.SkuID)
		skus := []map[string]interface{}{
			map[string]interface{}{
				"sku_id": foodData[mtwmapi.KeyAppFoodCode],
			},
		}
		foodData["skus"] = skus
		foodData["name"] = utils.LimitUTF8StringLen(storeSku.SkuName, mtwmapi.MaxSkuNameCharCount)
		foodData["description"] = storeSku.Comment
		if isNeedUpdatePrice {
			foodData["price"] = jxutils.IntPrice2Standard(storeSku.VendorPrice)
		}
		if storeSku.MinOrderCount != 0 {
			foodData["min_order_count"] = storeSku.MinOrderCount
		} else {
			foodData["min_order_count"] = 1
		}
		foodData["unit"] = storeSku.Unit
		//todo 增加商品必填属性
		attr := SwitchAttr(getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID), vendorStoreID, storeSku.VendorVendorCatID, storeSku.NameID, storeSku.Name)
		if attr != "" {
			foodData["common_attr_value"] = attr
		}
		if storeSku.SellPoint != "" {
			foodData["sell_point"] = storeSku.SellPoint
		}
		if storeSku.SellPointTimes != "" {
			foodData["sell_point_available_times"] = storeSku.SellPointTimes
		}
		catCode := tryCatName2Code(storeSku.VendorCatID)
		if catCode != "" {
			foodData["category_code"] = catCode
		} else {
			foodData["category_name"] = storeSku.VendorCatID
		}
		foodData["is_sold_out"] = skuStatusJX2Mtwm(storeSku.MergedStatus)
		if true { // vendorStoreID == specialStoreID {
			img2 := storeSku.Img2
			img3 := storeSku.Img3
			img4 := storeSku.Img4
			img5 := storeSku.Img5
			//if img2 == "" {
			//	img2 = storeSku.Img
			//}
			//if img3 == "" {
			//	img3 = storeSku.Img
			//}
			//if img4 == "" {
			//	img4 = storeSku.Img
			//}
			//if img5 == "" {
			//	img5 = storeSku.Img
			//}
			if storeSku.ImgMix != "" && ((storeSku.BrandID == storeSku.ExBrandID && storeSku.ExBrandID != 0) || storeSku.ExBrandID == 0) {
				foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.ImgMix, storeSku.Img, img2, img3, img4, img5), ",")
			} else {
				foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, img2, img3, img4, img5), ",")
			}
		} else {
			foodData["picture"] = strings.Join(jxutils.BatchString2Slice(storeSku.Img, storeSku.Img2), ",")
		}
		if storeSku.DescImg != "" {
			foodData["picture_contents"] = storeSku.DescImg
		}
		if storeSku.QuaPictures != "" {
			foodData["qua_pictures"] = storeSku.QuaPictures
			foodData["qua_effective_date"] = storeSku.QuaEffectiveDate
			foodData["qua_approval_date"] = storeSku.QuaApprovalDate
		}
		if storeSku.SpecialPictures != "" {
			foodData["special_pictures"] = storeSku.SpecialPictures
		}

		// 周期性可售时间段
		if storeSku.StatusSaleBegin != model.NO && storeSku.StatusSaleEnd != model.NO {
			saleStart := utils.Int2Str(int(storeSku.StatusSaleBegin))
			saleEnd := utils.Int2Str(int(storeSku.StatusSaleEnd))
			for {
				if len(saleStart) != 4 {
					saleStart = "0" + saleStart
				}
				if len(saleEnd) != 4 {
					saleEnd = "0" + saleEnd
				}
				if len(saleEnd) == 4 && len(saleStart) == 4 {
					break
				}
			}
			saleStart = fmt.Sprintf("%s:%s", saleStart[:2], saleStart[2:])
			saleEnd = fmt.Sprintf("%s:%s", saleEnd[:2], saleEnd[2:])
			availableTimes := fmt.Sprintf("%s-%s", saleStart, saleEnd)
			available, _ := json.Marshal(map[string]string{"monday": availableTimes, "tuesday": availableTimes, "wednesday": availableTimes, "thursday": availableTimes, "friday": availableTimes, "saturday": availableTimes, "sunday": availableTimes})
			foodData["available_times"] = string(available)
		} else {
			foodData["all_available_times"] = "EMPTY_VALUE" // 清空可售时间段
		}

		foodData["sequence"] = storeSku.GetSeq()
		if storeSku.VendorVendorCatID != 0 {
			foodData["tag_id"] = utils.Int64ToStr(storeSku.VendorVendorCatID)
		} else {
			// foodData["tag_id"] = utils.Int64ToStr(defVendorCatID)
		}
		skus[0]["spec"] = jxutils.ComposeSkuSpec(storeSku.SpecQuality, storeSku.SpecUnit)
		if isNeedUpdatePrice {
			skus[0]["price"] = foodData["price"]
		}
		skus[0]["stock"] = stockCount2Mtwm(storeSku.Stock)
		if storeSku.Upc != "" {
			skus[0]["upc"] = storeSku.Upc
		}
		if storeSku.LocationCode != "" {
			skus[0]["location_code"] = storeSku.LocationCode
		}
		//skus[0]["ladder_box_num"] = "0"
		//skus[0]["ladder_box_price"] = "0"
		// 下面这个两个和上面有点重复,但是上面两个在更新的时候美团不识别,不知道创建的时候会不会覆盖一下吧(更新只能用下面这个)
		skus[0]["box_num"] = "0"
		skus[0]["box_price"] = "0"
		if foodData["tag_id"] != nil {
			skus[0]["weight"] = storeSku.Weight // weight字段仅限服饰鞋帽、美妆、日用品、母婴、生鲜果蔬、生活超市下的便利店/超市门店品类的商家使用
		}

	}

	api := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID)
	if globals.EnableMtwmStoreWrite {
		if len(foodDataList) == 1 {
			foodDataList[0]["skus"] = string(utils.MustMarshal(foodDataList[0]["skus"]))
			if err = api.RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0]); err != nil {
				failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType)
			}
		} else if len(foodDataList) > 0 {
			failedFoodList, err2 := api.RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList)
			if err = err2; err == nil {
				if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil {
					failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType)
					// successList = putils.UnselectStoreSkuSyncListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList))
				}
			} else if err2 != nil && len(failedFoodList) == 0 {
				if errExt, ok := err2.(*utils.ErrorWithCode); ok {
					err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
					failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], syncType)
				}
			}
		}
	}

	storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, "")
	spuList := make([]*mtwmapi.SpuData, 0, 0)
	for _, storeSku := range storeSkuList {
		if storeDetail.QuotationPrice != 0 && storeDetail.PayPercentage >= 50 {
			spuList = append(spuList, &mtwmapi.SpuData{
				AppSpuCode:    utils.Int2Str(storeSku.SkuID),
				SkuID:         utils.Int2Str(storeSku.SkuID),
				PurchasePrice: utils.Float64ToStr(float64(storeDetail.QuotationPrice) / float64(100)),
			})
		}
		storeSku.VendorSkuID = utils.Int2Str(storeSku.SkuID)
	}
	if len(failedList) > 0 {
		err = nil
	}

	// 报价门店同步进货价
	if len(spuList) > 0 {
		count := len(spuList) / 50
		if len(spuList)%50 != 0 {
			count++
		}
		for i := 1; i <= count; i++ {
			if i == count {
				api.BatchSetRestockingPrice(utils.GetUUID(), vendorStoreID, spuList[(i-1)*50:])
			} else {
				api.BatchSetRestockingPrice(utils.GetUUID(), vendorStoreID, spuList[(i-1)*50:i*50])
			}
		}
	}

	return failedList, err
}

func getAppFoodCodeList(l []*mtwmapi.AppFoodResult) (vendorSkuIDs []string) {
	if len(l) > 0 {
		vendorSkuIDs = make([]string, len(l))
		for k, v := range l {
			vendorSkuIDs[k] = v.AppFoodCode
		}
	}
	return vendorSkuIDs
}

func (p *PurchaseHandler) DeleteStoreSkus(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	if globals.EnableMtwmStoreWrite {
		if len(storeSkuList) == 1 {
			err = getAPI(storeSkuList[0].VendorOrgCode, storeID, vendorStoreID).RetailDelete(ctx.GetTrackInfo(), vendorStoreID, storeSkuList[0].VendorSkuID)
			failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDMTWM], "删除商品")
		} else {
			// todo 部分失败
			err = getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID).RetailCatSkuBatchDelete2(ctx.GetTrackInfo(), vendorStoreID, nil, nil, nil, nil, partner.BareStoreSkuInfoList(storeSkuList).GetVendorSkuIDList())
			if err != nil {
				if errExt, ok := err.(*utils.ErrorWithCode); ok {
					myMap := make(map[string][]*mtwmapi.AppFoodResult)
					json.Unmarshal([]byte(errExt.ErrMsg()), &myMap)
					failedList = SelectStoreSkuListByFoodList(storeSkuList, myMap["retail_error_list"], storeID, model.VendorChineseNames[model.VendorIDMTWM], "批量删除商品")
				}
			}
		}
	}
	if len(failedList) > 0 {
		err = nil
	}
	return failedList, err
}

// CommonAttrValue 类目对应属性值
type CommonAttrValue struct {
	AttrID    int         `json:"attr_id"`   //普通属性Id
	AttrName  string      `json:"attr_name"` //普通属性名称
	ValueList []ValueList `json:"valueList"`
}
type ValueList struct {
	ValueID int    `json:"value_id"` //普通属性值Id，当属性值录入方式为文本时，该参数无需上传；若该普通属性可扩展则支持自定义 1.负值 2.同一个商品的同一个普通属性内唯一
	Value   string `json:"value"`    //普通属性值名称(与普通属性值Id一一对应)，支持自定义。
}

func SwitchAttr(apiObj *mtwmapi.API, vendorStoreID string, vendorCatID int64, nameID int, name string) (attrs string) {
	var (
		db         *dao.DaoDB
		tempCatID  int64
		attrValue  CommonAttrValue
		attrValues []CommonAttrValue
	)
	if nameID != 0 { //是否为纯创建
		if tData, err := dao.GetSkuNames(db, []int{nameID}, nil, "", false); err == nil && len(tData) > 0 {
			if tData[0].MtAttribute != "[]" && tData[0].MtAttribute != "{}" && tData[0].MtAttribute != "" {
				return tData[0].MtAttribute
			}
		}
	}
	if vendorCatID == 0 { //创建商品时无分类，使用推荐分类
		if comTag, err := apiObj.RetailRecommendTag(name, vendorStoreID, 0, mtwmapi.TypeCategory); err == nil && comTag.TagID != 0 {
			tempCatID = int64(comTag.TagID)
		}
	} else {
		tempCatID = vendorCatID
	}
	//根据类目id获取类目属性列表
	if attrList, err := apiObj.CategoryAttrList(tempCatID); err == nil && len(attrList) > 0 {
		for _, v := range attrList {
			if v.Need == mtwmapi.NeedYes {
				attrValue = CommonAttrValue{
					AttrID:   utils.Str2Int(v.AttrID),
					AttrName: v.AttrName,
				}
				if v.AttrID == mtwmapi.SpecialAttrBrand || v.AttrID == mtwmapi.SpecialAttrProducer { //单独获取特殊属性
					data, err1 := apiObj.CategoryAttrValueList(utils.Str2Int64(v.AttrID), name)
					if len(data) > 0 {
						attrValue.ValueList = []ValueList{{ //默认取推荐第一个
							ValueID: utils.Str2Int(data[0].ValueID),
							Value:   data[0].Value,
						}}
					}
					if err1 != nil || len(data) == 0 {
						attrValue.ValueList = []ValueList{{ //兜底处理
							Value: "其他",
						}}
					}
				} else if v.AttrID == mtwmapi.SpecialAttrOrigin { // 产地默认国产
					attrValue.ValueList = []ValueList{{
						ValueID: 1300000003,
						Value:   "国产",
					}}
				} else {
					if len(v.ValueList) > 0 {
						attrValue.ValueList = []ValueList{{
							ValueID: utils.Str2Int(v.ValueList[0].ValueID),
							Value:   v.ValueList[0].Value,
						}}
					} else { //兜底处理
						attrValue.ValueList = []ValueList{{
							Value: "其他",
						}}
					}
				}
				attrValues = append(attrValues, attrValue)
			}
		}
		temp, _ := json.Marshal(attrValues)
		attrs = string(temp)
	} else {
		switch vendorCatID { //兜底处理
		case 200002727:
			attrs = mtwmapi.MtwmSkuAttr200002727
		case 200001555:
			attrs = mtwmapi.MtwmSkuAttr200001555
		case 200002728:
			attrs = mtwmapi.MtwmSkuAttr200002728
		case 200001519, 200000592:
			attrs = mtwmapi.MtwmSkuAttr200000592
		case 200002704, 200002731:
			attrs = mtwmapi.MtwmSkuAttr200002731
		case 200002716:
			attrs = mtwmapi.MtwmSkuAttr200002716
		case 200002667, 200002713, 200002670:
			attrs = mtwmapi.MtwmSkuAttr200002670
		case 200002680:
			attrs = mtwmapi.MtwmSkuAttr200002680
		default:
			attrs = ""
		}
	}
	//更新进数据库
	dao.UpdateSkuNameMtAttr(db, int64(nameID), attrs)
	return attrs
}

func stockCount2Mtwm(stock int) (mtwmStock string) {
	if stock == 0 && beego.BConfig.RunMode != model.ServerTypePet {
		stock = model.MaxStoreSkuStockQty
	}
	return utils.Int2Str(stock)
}

func storeSku2Mtwm(storeSkuList []*partner.StoreSkuInfo, updateType int) (skuList []*mtwmapi.BareStoreFoodInfo) {
	for _, storeSku := range storeSkuList {
		skuInfo := &mtwmapi.BareStoreFoodInfo{
			AppFoodCode: storeSku.VendorSkuID,
			Skus: []*mtwmapi.BareStoreSkuInfo{
				&mtwmapi.BareStoreSkuInfo{
					SkuID: storeSku.VendorSkuID,
				},
			},
		}
		if updateType == updateTypeStock {
			skuInfo.Skus[0].Stock = stockCount2Mtwm(storeSku.Stock)
		} else if updateType == updateTypePrice {
			skuInfo.Skus[0].Price = jxutils.IntPrice2StandardString(storeSku.VendorPrice)
		} else {
			skuInfo.Skus = nil
		}
		skuList = append(skuList, skuInfo)
	}
	return skuList
}

func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	skuList := storeSku2Mtwm(storeSkuList, updateTypeStatus)
	mtwmStatus := skuStatusJX2Mtwm(status)
	if globals.EnableMtwmStoreWrite {
		failedFoodList, err2 := getAPI(vendorOrgCode, storeID, vendorStoreID).RetailSellStatus(ctx.GetTrackInfo(), vendorStoreID, skuList, mtwmStatus)
		if err = err2; err == nil {
			if len(failedFoodList) > 0 {
				failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品状态")
				// successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList))
			}
		} else if err2 != nil && len(failedFoodList) == 0 {
			if errExt, ok := err2.(*utils.ErrorWithCode); ok {
				err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
				failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品状态")
			}
		}
	}
	if len(failedList) > 0 {
		err = nil
	}
	return failedList, err
}

func (p *PurchaseHandler) UpdateStoreSkusPrice(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	priceList := storeSku2Mtwm(storeSkuList, updateTypePrice)
	api := getAPI(vendorOrgCode, storeID, vendorStoreID)
	if globals.EnableMtwmStoreWrite {
		failedFoodList, err2 := api.RetailSkuPrice(ctx.GetTrackInfo(), vendorStoreID, priceList)
		if err = err2; err == nil {
			if len(failedFoodList) > 0 {
				failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品价格")
			}
		} else if err2 != nil && len(failedFoodList) == 0 {
			if errExt, ok := err2.(*utils.ErrorWithCode); ok {
				err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
				failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品价格")
			}
		}
	}
	if len(failedList) > 0 {
		err = nil
	}
	// 改价的同时去修改报价门店的进货价
	storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDMTWM, "")
	spuList := make([]*mtwmapi.SpuData, 0, 0)
	for _, storeSku := range storeSkuList {
		if storeDetail.QuotationPrice != 0 && storeDetail.PayPercentage >= 50 {
			spuList = append(spuList, &mtwmapi.SpuData{
				AppSpuCode:    utils.Int2Str(storeSku.SkuID),
				SkuID:         utils.Int2Str(storeSku.SkuID),
				PurchasePrice: utils.Float64ToStr(float64(storeDetail.QuotationPrice) / float64(100)),
			})
		}
	}
	// 报价门店同步进货价
	if len(spuList) > 0 {
		count := len(spuList) / 50
		if len(spuList)%50 != 0 {
			count++
		}
		for i := 1; i <= count; i++ {
			if i == count {
				api.BatchSetRestockingPrice(utils.GetUUID(), vendorStoreID, spuList[(i-1)*50:])
			} else {
				api.BatchSetRestockingPrice(utils.GetUUID(), vendorStoreID, spuList[(i-1)*50:i*50])
			}
		}
	}

	return failedList, err
}

func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	stockList := storeSku2Mtwm(storeSkuList, updateTypeStock)
	if globals.EnableMtwmStoreWrite {
		failedFoodList, err2 := getAPI(vendorOrgCode, storeID, vendorStoreID).RetailSkuStock(ctx.GetTrackInfo(), vendorStoreID, stockList)
		if err = err2; err == nil {
			if len(failedFoodList) > 0 {
				failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品库存")
			}
			//if err = putils.GenPartialFailedErr(failedFoodList, len(failedFoodList)); err != nil {
			// successList = putils.UnselectStoreSkuListByVendorSkuIDs(storeSkuList, getAppFoodCodeList(failedFoodList))
			// }
		} else if err2 != nil && len(failedFoodList) == 0 {
			if errExt, ok := err2.(*utils.ErrorWithCode); ok {
				err = utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &failedFoodList)
				failedList = SelectStoreSkuListByFoodList(storeSkuList, failedFoodList, storeID, model.VendorChineseNames[model.VendorIDMTWM], "更新商品库存")
			}
		}
	}
	if len(failedList) > 0 {
		err = nil
	}
	return failedList, err
}

func mtwmSkuStatus2Jx(mtwmSkuStatus int) (jxSkuStatus int) {
	if mtwmSkuStatus == mtwmapi.SellStatusOnline {
		jxSkuStatus = model.SkuStatusNormal
	} else {
		jxSkuStatus = model.SkuStatusDontSale
	}
	return jxSkuStatus
}

func (p *PurchaseHandler) GetStoreSkusFullInfo(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (skuNameList []*partner.SkuNameInfo, err error) {
	if len(storeSkuList) == 1 {
		skuInfo, err := getAPI(storeSkuList[0].VendorOrgCode, storeID, vendorStoreID).RetailGet(vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID))
		if err != nil {
			return nil, err
		}
		if skuName := vendorSku2Jx(skuInfo); skuName != nil {
			skuNameList = append(skuNameList, skuName)
		}
	} else {
		var storeSkuMap map[string]*partner.StoreSkuInfo
		if storeSkuList != nil {
			storeSkuMap = putils.StoreSkuList2MapByVendorSkuID(storeSkuList)
		}
		mtapi := getAPI(getStoreVendorOrgCode(storeID), storeID, vendorStoreID)
		for {
			// todo 待优化获取速度
			result, err := mtapi.RetailList(vendorStoreID, len(skuNameList), mtwmapi.GeneralMaxLimit)
			if err != nil {
				return nil, err
			}
			if storeSkuMap == nil {
				skuNameList = append(skuNameList, vendorSkuList2Jx(result)...)
			} else {
				for _, v := range result {
					if storeSkuMap[v.AppFoodCode] != nil {
						if skuName := vendorSku2Jx(v); skuName != nil {
							skuNameList = append(skuNameList, skuName)
						}
					}
				}
			}
			if len(result) < mtwmapi.GeneralMaxLimit {
				break
			}
		}
	}
	return skuNameList, err
}

func vendorSku2Jx(appFood *mtwmapi.AppFood) (skuName *partner.SkuNameInfo) {
	if len(appFood.SkuList) == 0 {
		return nil
	}
	prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(appFood.Name)
	vendorSku := appFood.SkuList[0]
	weight := int(utils.Str2Int64WithDefault(vendorSku.Weight, 0))
	if weight <= 0 {
		weight = jxutils.FormatSkuWeight(specQuality, specUnit)
	}
	skuID := int(utils.Str2Int64WithDefault(vendorSku.SkuId, 0))
	skuName = &partner.SkuNameInfo{
		NameID:       int(utils.Str2Int64WithDefault(appFood.AppFoodCode, 0)),
		VendorNameID: appFood.AppFoodCode,
		UPC:          appFood.SkuList[0].Upc,
		Prefix:       prefix,
		Name:         name,
		Unit:         unit,
		Status:       mtwmSkuStatus2Jx(appFood.IsSoldOut), //此处为之前一个bug 如果吧状态放到切片内层  对于内层函数中映射无法关联 永远获取到的初始值为0
		SkuList: []*partner.SkuInfo{
			&partner.SkuInfo{
				StoreSkuInfo: partner.StoreSkuInfo{
					VendorSkuID: vendorSku.SkuId,
					SkuID:       skuID,
					IsSpecialty: appFood.IsSpecialty,
					Stock:       int(utils.Str2Int64WithDefault(vendorSku.Stock, partner.UnlimitedStoreSkuStock)),
					VendorPrice: jxutils.StandardPrice2Int(utils.Str2Float64WithDefault(vendorSku.Price, 0)),
					Status:      mtwmSkuStatus2Jx(appFood.IsSoldOut),
				},
				SkuName:     appFood.Name,
				Comment:     comment,
				SpecQuality: float64(specQuality),
				SpecUnit:    specUnit,
				Weight:      weight,
			},
		},
		PictureList: appFood.PictureList,
	}
	if appFood.CategoryName != "" {
		// todo, 因为当前我们用的是分类名操作这种方式，所以要返回分类名（而不是分类code）
		skuName.VendorCatIDList = []string{appFood.CategoryName}
		if appFood.SecondaryCategoryName != "" {
			skuName.VendorCatIDList = append(skuName.VendorCatIDList, appFood.SecondaryCategoryName)
		}
	}
	return skuName
}

func vendorSkuList2Jx(appFoodList []*mtwmapi.AppFood) (skuNameList []*partner.SkuNameInfo) {
	for _, appFood := range appFoodList {
		if skuName := vendorSku2Jx(appFood); skuName != nil {
			skuNameList = append(skuNameList, skuName)
		}
	}
	return skuNameList
}

func (p *PurchaseHandler) GetSensitiveWordRegexp() *regexp.Regexp {
	return sensitiveWordRegexp
}

//美团api返回
func SelectStoreSkuListByFoodList(storeSkuList interface{}, foodList []*mtwmapi.AppFoodResult, storeID int, vendorName, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) {
	foodMap := make(map[string]string)
	if len(foodList) > 0 {
		for _, v := range foodList {
			foodMap[v.AppFoodCode] = v.ErrorMsg
		}
		if storeSkuLists, ok := storeSkuList.([]*partner.StoreSkuInfo); ok {
			for _, v := range storeSkuLists {
				if foodMap[v.VendorSkuID] != "" {
					foodFailed := &partner.StoreSkuInfoWithErr{
						StoreSkuInfo: v,
						ErrMsg:       foodMap[v.VendorSkuID],
						StoreID:      storeID,
						VendoreName:  vendorName,
						SyncType:     syncType,
					}
					selectedStoreSkuList = append(selectedStoreSkuList, foodFailed)
				}
			}
		}
		if storeSkuLists, ok := storeSkuList.([]*dao.StoreSkuSyncInfo); ok {
			for _, v := range storeSkuLists {
				if foodMap[v.VendorSkuID] != "" {
					storeSkuInfo := &partner.StoreSkuInfo{
						SkuID:        v.SkuID,
						VendorSkuID:  v.VendorSkuID,
						NameID:       v.NameID,
						VendorNameID: v.VendorNameID,
						VendorPrice:  v.VendorPrice,
						Status:       v.Status,
					}
					foodFailed := &partner.StoreSkuInfoWithErr{
						StoreSkuInfo: storeSkuInfo,
						ErrMsg:       foodMap[v.VendorSkuID],
						StoreID:      storeID,
						VendoreName:  vendorName,
						SyncType:     syncType,
					}
					selectedStoreSkuList = append(selectedStoreSkuList, foodFailed)
				}
			}
		}
	}
	return selectedStoreSkuList
}

func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	actStoreSkuList := putils.StoreSku2ActStoreSku(model.SyncFlagNewMask, vendorStoreID, storeSkuList)
	failedList, err = createOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, actStoreSkuList)
	storeSkuMap := putils.StoreSkuList2MapBySkuID(storeSkuList)
	for _, v := range actStoreSkuList {
		storeSkuMap[v.SkuID].VendorActID = v.VendorActID
	}
	if len(failedList) > 0 {
		err = nil
	}
	return failedList, err
}

func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	return cancelOneShopAct(putils.GetFixDirectDownAct(vendorOrgCode, storeID, 0), vendorStoreID, putils.StoreSku2ActStoreSku(model.SyncFlagDeletedMask, vendorStoreID, storeSkuList))
}

// UpdateStoreSkusSpecTag 更新限购
func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) {
	var foodDataList = []map[string]interface{}{}
	for _, v := range storeSkuList {
		var foodData = make(map[string]interface{})
		if v.IsSpecialty == -1 {
			v.IsSpecialty = 0
		}
		foodData["is_specialty"] = v.IsSpecialty
		foodData["app_food_code"] = v.SkuID
		foodDataList = append(foodDataList, foodData)
	}
	if globals.EnableMtwmStoreWrite {
		if len(foodDataList) == 1 {
			err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailInitData(ctx.GetTrackInfo(), vendorStoreID, utils.Int2Str(storeSkuList[0].SkuID), foodDataList[0])
		} else if len(foodDataList) > 0 {
			_, err = getAPI(vendorOrgCode, storeID, vendorStoreID).RetailBatchInitData(ctx.GetTrackInfo(), vendorStoreID, foodDataList)
		}
	}
	return err
}

func (p *PurchaseHandler) GetSkuCategoryIdByName(vendorOrgCode, skuName string) (vendorCategoryId string, err error) {
	return "", err
}

type SetBoxPrice struct {
	StoreId  int     `json:"store_id"`  // 门店id
	SkuId    int     `json:"sku_id"`    // 商品id
	BoxPrice float64 `json:"box_price"` // 打包价格
}

func UpdateBoxPrice(ctx *jxcontext.Context, db *dao.DaoDB, list []int) error {
	for _, v := range list {
		storeDetail, err := dao.GetStoreDetail(db, v, model.VendorIDMTWM, "")
		if err != nil {
			return err
		}

		skuList, err := dao.GetStoreSkuBindList(db, v)
		if err != nil {
			return err
		}
		if len(skuList) == model.NO {
			continue
		}

		foodDataList := make([]map[string]interface{}, 0)
		for _, sl := range skuList {
			foodDataList = append(foodDataList, map[string]interface{}{
				"app_spu_code": utils.Int2Str(sl.SkuID),
				"skus": []map[string]interface{}{
					{
						"sku_id":           utils.Int2Str(sl.SkuID),
						"ladder_box_num":   "0",
						"ladder_box_price": "0",
					},
				},
			})
		}

		count := utils.Float64TwoInt(math.Ceil(float64(len(foodDataList)) / float64(200)))
		api := getAPI(storeDetail.VendorOrgCode, v, storeDetail.VendorStoreID)
		for i := 1; i <= count; i++ {
			api.SetToken(storeDetail.MtwmToken)
			if i == count {
				result, err := api.RetailBatchInitData2(ctx.GetTrackInfo(), storeDetail.VendorStoreID, foodDataList[(i-1)*200:])
				if err != nil {
					globals.SugarLogger.Debugf("RetailBatchInitData1 err := %v", err)
				}
				if result != nil {
					globals.SugarLogger.Debugf("RetailBatchInitData1 result := %s", utils.Format4Output(result, false))
				}
			} else {
				result, err := api.RetailBatchInitData2(ctx.GetTrackInfo(), storeDetail.VendorStoreID, foodDataList[(i-1)*200:i*200])
				if err != nil {
					globals.SugarLogger.Debugf("RetailBatchInitData2 err := %v", err)
				}
				if result != nil {
					globals.SugarLogger.Debugf("RetailBatchInitData1 result := %s", utils.Format4Output(result, false))
				}
			}
		}
	}

	return nil
}
