package jd

import (
	"git.rosy.net.cn/baseapi/platformapi/jdapi"
	"git.rosy.net.cn/baseapi/utils"
	"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"
	"git.rosy.net.cn/jx-callback/globals/api/apimanager"
)

func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
	switch funcID {
	case partner.FuncUpdateStoreSkusStock, partner.FuncUpdateStoreSkusStatus, partner.FuncUpdateStoreSkusPrice:
		batchSize = jdapi.MaxStoreSkuBatchSize
	case partner.FuncCreateActs, partner.FuncCancelActs:
		batchSize = 1
	}
	return batchSize
}

func (p *PurchaseHandler) getStoreSkusBareInfoLimitSize(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) {
	var batchSkuInfoList []*jdapi.BaseStockCenterRequest
	batchSkuList := partner.BareStoreSkuInfoList(inStoreSkuList).GetVendorSkuIDIntList()
	for _, v := range inStoreSkuList {
		if !dao.IsVendorThingIDEmpty(v.VendorSkuID) {
			batchSkuInfoList = append(batchSkuInfoList, &jdapi.BaseStockCenterRequest{
				StationNo: vendorStoreID,
				SkuId:     utils.Str2Int64(v.VendorSkuID),
			})
		}
	}
	if len(batchSkuInfoList) > 0 {
		var stockInfo []*jdapi.QueryStockResponse
		var priceInfo []*jdapi.StorePriceInfo
		task := tasksch.NewParallelTask("获取京东到家平台门店商品信息", tasksch.NewParallelConfig().SetParallelCount(2), ctx,
			func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
				subTaskID := batchItemList[0].(int)
				if subTaskID == 0 {
					stockInfo, err = getAPI(vendorOrgCode).QueryOpenUseable(batchSkuInfoList)
				} else {
					priceInfo, err = getAPI(vendorOrgCode).GetStationInfoList(vendorStoreID, batchSkuList)
				}
				return nil, err
			}, []int{0, 1})
		tasksch.HandleTask(task, parentTask, false).Run()
		_, err = task.GetResult(0)
		if err == nil {
			storeSkuMap := putils.StoreSkuList2MapByVendorSkuID(inStoreSkuList)
			for _, v := range stockInfo {
				sku := storeSkuMap[utils.Int64ToStr(v.SkuID)]
				sku.Status = jdStoreSkuStatus2Jx(v.Vendibility)
				sku.Stock = v.UsableQty
				// if sku.Stock > 0 {
				outStoreSkuList = append(outStoreSkuList, sku)
				// }
			}
			for _, v := range priceInfo {
				sku := storeSkuMap[utils.Int64ToStr(v.SkuID)]
				sku.VendorPrice = v.Price
			}
		}
	}
	return outStoreSkuList, err
}

func (p *PurchaseHandler) GetStoreSkusBareInfo(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, vendorStoreID string, inStoreSkuList []*partner.StoreSkuInfo) (outStoreSkuList []*partner.StoreSkuInfo, err error) {
	result, err := putils.FreeBatchStoreSkuInfo("获取门店商品信息", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) {
		list, err := p.getStoreSkusBareInfoLimitSize(ctx, vendorOrgCode, task, storeID, vendorStoreID, batchedStoreSkuList)
		if err == nil {
			result = list
		}
		return result, len(list), err
	}, ctx, parentTask, inStoreSkuList, jdapi.MaxStoreSkuBatchSize, true)
	for _, v := range result {
		outStoreSkuList = append(outStoreSkuList, v.(*partner.StoreSkuInfo))
	}
	return outStoreSkuList, err
}

func jdStoreSkuStatus2Jx(jdStoreSkuStatus int) (jxSkuStatus int) {
	if jdStoreSkuStatus == 0 {
		jxSkuStatus = model.SkuStatusNormal
	} else {
		jxSkuStatus = model.SkuStatusDontSale
	}
	return jxSkuStatus
}

func jxStoreSkuStatus2Jd(jxStoreSkuStatus int) (isSale bool) {
	return jxStoreSkuStatus == model.SkuStatusNormal
}

func isErrPartialFailed(err error) bool {
	if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.Code() == jdapi.ResponseInnerCodePartialFailed {
		return true
	}
	return false
}

func getStrOutSkuIDs(l []*jdapi.StoreSkuBatchUpdateResponse, isSuccess bool) (outSkuIDs []string) {
	for _, v := range l {
		if isSuccess && jdapi.IsCodeSuccess(v.Code) {
			outSkuIDs = append(outSkuIDs, v.OutSkuID)
		} else if !isSuccess && !jdapi.IsCodeSuccess(v.Code) {
			outSkuIDs = append(outSkuIDs, v.OutSkuID)
		}
	}
	return outSkuIDs
}

func (p *PurchaseHandler) UpdateStoreSkusStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo, status int) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	var skuVendibilityList []*jdapi.StockVendibility
	jdStatus := jxStoreSkuStatus2Jd(status)
	for _, v := range storeSkuList {
		skuVendibilityList = append(skuVendibilityList, &jdapi.StockVendibility{
			OutSkuId: utils.Int2Str(v.SkuID),
			DoSale:   jdStatus,
		})
	}
	if globals.EnableJdStoreWrite {
		var responseList []*jdapi.StoreSkuBatchUpdateResponse
		var err2 error
		if vendorOrgCode != apimanager.FakeJdOrgCode {
			responseList, err2 = getAPI(vendorOrgCode).BatchUpdateVendibility(ctx.GetTrackInfo(), "", vendorStoreID, skuVendibilityList, ctx.GetUserName())
		} else {
			responseList, err2 = getAPI(vendorOrgCode).FakeBatchUpdateVendibility(ctx.GetTrackInfo(), "", vendorStoreID, skuVendibilityList, ctx.GetUserName())
		}
		if err = err2; err != nil {
			failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品状态")
			// successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false)))
		}
	}
	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) {
	if len(storeSkuList) == 1 && vendorOrgCode != apimanager.FakeJdOrgCode {
		if globals.EnableJdStoreWrite {
			_, err = getAPI(vendorOrgCode).UpdateStationPrice(ctx.GetTrackInfo(), utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), vendorStoreID, int(storeSkuList[0].VendorPrice))
			failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品价格")
		}
	} else {
		var skuPriceInfoList []*jdapi.SkuPriceInfo
		for _, v := range storeSkuList {
			skuPriceInfoList = append(skuPriceInfoList, &jdapi.SkuPriceInfo{
				OutSkuId: utils.Int2Str(v.SkuID),
				Price:    int(v.VendorPrice),
			})
		}
		if globals.EnableJdStoreWrite {
			var responseList []*jdapi.StoreSkuBatchUpdateResponse
			var err2 error
			if vendorOrgCode != apimanager.FakeJdOrgCode {
				responseList, err2 = getAPI(vendorOrgCode).UpdateVendorStationPrice(ctx.GetTrackInfo(), "", vendorStoreID, skuPriceInfoList)
			} else {
				responseList, err2 = getAPI(vendorOrgCode).FakeUpdateVendorStationPrice(ctx.GetTrackInfo(), "", vendorStoreID, skuPriceInfoList)
			}
			if err = err2; err != nil {
				failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品价格")
			}
		}
	}
	err = nil
	return failedList, err
}

func (p *PurchaseHandler) UpdateStoreSkusStock(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	if len(storeSkuList) == 1 && vendorOrgCode != apimanager.FakeJdOrgCode {
		if globals.EnableJdStoreWrite {
			err = getAPI(vendorOrgCode).UpdateCurrentQty(ctx.GetTrackInfo(), vendorStoreID, utils.Str2Int64WithDefault(storeSkuList[0].VendorSkuID, 0), storeSkuList[0].Stock)
			failedList = putils.GetErrMsg2FailedSingleList(storeSkuList, err, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品库存")
		}
	} else {
		var skuStockList []*jdapi.SkuStock
		for _, v := range storeSkuList {
			skuStockList = append(skuStockList, &jdapi.SkuStock{
				OutSkuId: utils.Int2Str(v.SkuID),
				StockQty: v.Stock,
			})
		}
		if globals.EnableJdStoreWrite {
			var responseList []*jdapi.StoreSkuBatchUpdateResponse
			var err2 error
			if vendorOrgCode != apimanager.FakeJdOrgCode {
				responseList, err2 = getAPI(vendorOrgCode).BatchUpdateCurrentQtys(ctx.GetTrackInfo(), "", vendorStoreID, skuStockList, ctx.GetUserName())
			} else {
				responseList, err2 = getAPI(vendorOrgCode).FakeBatchUpdateCurrentQtys(ctx.GetTrackInfo(), "", vendorStoreID, skuStockList, ctx.GetUserName())
			}
			if err = err2; err != nil {
				failedList = SelectStoreSkuListByResponseList(storeSkuList, responseList, storeID, model.VendorChineseNames[model.VendorIDJD], "更新商品库存")
				// successList = putils.UnselectStoreSkuListBySkuIDs(storeSkuList, utils.StringSlice2Int(getStrOutSkuIDs(responseList, false)))
			}
		}
	}
	err = nil
	return failedList, err
}

func (p *PurchaseHandler) SyncStoreProducts(ctx *jxcontext.Context, vendorOrgCode string, parentTask tasksch.ITask, storeID int, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
	db := dao.GetDB()
	storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJD, "")
	if err != nil {
		return "", err
	}
	storeSkuList, err := dao.GetStoreSkus2(db, model.VendorIDJD, storeID, skuIDs, false)
	if err != nil {
		return "", err
	}
	task := tasksch.NewParallelTask("SyncStoreProducts京东", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			storeSku := batchItemList[0].(*dao.StoreSkuSyncInfo)
			if storeSku.VendorSkuID != "" && storeSku.StoreSkuStatus == model.SkuStatusNormal {
				if globals.EnableJdStoreWrite {
					synchronized, err2 := getAPI(vendorOrgCode).SyncProduct(storeDetail.VendorStoreID, storeSku.VendorSkuID)
					if err = err2; err == nil && synchronized {
						retVal = []int{1}
					}
				} else {
					retVal = []int{1}
				}
			}
			return retVal, err
		}, storeSkuList)
	tasksch.HandleTask(task, parentTask, true).Run()
	if !isAsync {
		result, err2 := task.GetResult(0)
		if err = err2; err == nil {
			hint = utils.Int2Str(len(result))
		}
	} else {
		hint = task.GetID()
	}
	return hint, err
}

//京东api返回
func SelectStoreSkuListByResponseList(storeSkuList []*partner.StoreSkuInfo, responseList []*jdapi.StoreSkuBatchUpdateResponse, storeID int, vendorName, syncType string) (selectedStoreSkuList []*partner.StoreSkuInfoWithErr) {
	responseMap := make(map[string]string)
	if len(responseList) > 0 {
		for _, v := range responseList {
			if v.Code != "0" {
				responseMap[v.OutSkuID] = v.Msg
			}
		}
		for _, v := range storeSkuList {
			if responseMap[utils.Int2Str(v.SkuID)] != "" {
				respFailed := &partner.StoreSkuInfoWithErr{
					StoreSkuInfo: v,
					ErrMsg:       responseMap[utils.Int2Str(v.SkuID)],
					StoreID:      storeID,
					VendoreName:  vendorName,
					SyncType:     syncType,
				}
				selectedStoreSkuList = append(selectedStoreSkuList, respFailed)
			}
		}
	}
	return selectedStoreSkuList
}

func (p *PurchaseHandler) CreateStoreSkusAct(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	for _, v := range storeSkuList {
		if vendorActID, err2 := createSkuAct(ctx, putils.GetFixDirectDownAct(vendorOrgCode, storeID, v.SkuID), putils.StoreSku2ActStoreSku(model.SyncFlagNewMask, vendorStoreID, []*partner.StoreSkuInfo{v})); err2 != nil {
			failedList = append(failedList, &partner.StoreSkuInfoWithErr{
				StoreSkuInfo: v,
				VendoreID:    model.VendorIDJD,
				StoreID:      storeID,
				ErrMsg:       err2.Error(),
			})
		} else {
			v.VendorActID = vendorActID
		}
	}
	return failedList, err
}

func (p *PurchaseHandler) CancelActs(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	for _, v := range storeSkuList {
		if err2 := cancelSkuAct(ctx, putils.GetFixDirectDownAct(vendorOrgCode, storeID, v.SkuID), v.VendorActID); err2 != nil {
			failedList = append(failedList, &partner.StoreSkuInfoWithErr{
				StoreSkuInfo: v,
				VendoreID:    model.VendorIDJD,
				StoreID:      storeID,
				ErrMsg:       err2.Error(),
			})
		}
	}
	return failedList, err
}

func (p *PurchaseHandler) UpdateStoreSkusSpecTag(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuList []*partner.StoreSkuInfo) (err error) {
	return err
}
