package tao_vegetable

import (
	"fmt"
	"math/rand"
	"time"

	"git.rosy.net.cn/baseapi/platformapi/tao_vegetable/sdk/ability2770/domain"

	"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
	"git.rosy.net.cn/baseapi/platformapi/tao_vegetable"
	"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"
)

func actType2Txd(actType int) int64 {
	if actType == model.ActSkuDirectDown {
		actType = tao_vegetable.DiscountTypeDeductMoney
	} else if actType == model.ActSkuSecKill {
		actType = tao_vegetable.DiscountTypeOnePrice
	} else if actType == model.ActSkuDiscount {
		actType = tao_vegetable.DiscountTypeDiscounts
	}
	return int64(actType)
}

func actOrderRules2Mtwm(actOrderRules []*model.ActOrderRule) (actDetails []*mtwmapi.FullDiscountActDetail) {
	for _, v := range actOrderRules {
		actDetails = append(actDetails, &mtwmapi.FullDiscountActDetail{
			OriginalPrice: jxutils.IntPrice2Standard(v.SalePrice),
			ActPrice:      jxutils.IntPrice2Standard(v.DeductPrice),
		})
	}
	return actDetails
}

//创建活动详情
func act2TxdActivity(act *model.Act2) (activity *domain.AlibabaRetailMarketingItemdiscountActivityCreateItemDiscountActivityOperateRequest) {
	actName := act.GetRealActName()
	activity = &domain.AlibabaRetailMarketingItemdiscountActivityCreateItemDiscountActivityOperateRequest{
		ActivityName: &actName,
		CreatorId:    utils.String2Pointer(utils.Int2Str(rand.Int())),
		CreatorName:  &act.LastOperator,
		Description:  &act.Advertising,
		Terminals:    &[]int32{tao_vegetable.TerminalsAPP},
		//StoreIds: &[]string{act.s},
		DiscountType: utils.Int64ToPointer(actType2Txd(act.Type)),
		StartTime:    utils.Int64ToPointer(act.BeginAt.UnixNano() / int64(time.Millisecond)),
		EndTime:      utils.Int64ToPointer(act.EndAt.UnixNano() / int64(time.Millisecond)),
	}
	return activity
}

func storeSku2ActData(act *model.Act2, actStoreSku []*model.ActStoreSku2, handler func(int8) bool) (actData *domain.AlibabaRetailMarketingItemdiscountActivitySkuAddItemDiscountActivityElementOperateRequest) {
	var (
		//limitCount = int64(1)
		//userLimitCount = int64(1)
		fixPriceMoney = int64(0)
		discountRate  = int64(0)
		decreaseMoney = int64(0)
		//limitDaily     = int64(1)
		skuElements []domain.AlibabaRetailMarketingItemdiscountActivitySkuAddSkuActivityElementDto
		skuElement  domain.AlibabaRetailMarketingItemdiscountActivitySkuAddSkuActivityElementDto
	)
	//if act.LimitCount > 0 {
	//	limitCount = int64(act.LimitCount)
	//	if act.LimitUser > 0 {
	//		userLimitCount = int64(act.LimitCount)
	//	}
	//} else if act.LimitDaily > 0 {
	//	limitDaily = int64(act.LimitDaily)
	//}
	actData = &domain.AlibabaRetailMarketingItemdiscountActivitySkuAddItemDiscountActivityElementOperateRequest{
		CreatorId:   utils.String2Pointer(utils.Int2Str(rand.Int())),
		CreatorName: &act.LastOperator,
		OutActId:    utils.String2Pointer(utils.Int2Str(act.Act.ID)),
	}
	for _, v := range actStoreSku {
		if handler == nil || handler(v.SyncStatus) {
			//stock := int64(0)
			//if v.Stock > 0 {
			//	stock = int64(v.Stock)
			//}

			sType := actType2Txd(act.Type)
			switch sType {
			case tao_vegetable.DiscountTypeDeductMoney:
				decreaseMoney = v.VendorPrice - v.ActualActPrice
				skuElement = domain.AlibabaRetailMarketingItemdiscountActivitySkuAddSkuActivityElementDto{
					SkuCode:       utils.String2Pointer(utils.Int2Str(v.SkuID)),
					DecreaseMoney: &decreaseMoney,
					//Limit: &domain.AlibabaRetailMarketingItemdiscountActivitySkuAddLimitDto{
					//	OrderLimitCnt: &limitCount,
					//},
				}
			case tao_vegetable.DiscountTypeOnePrice:
				fixPriceMoney = v.ActualActPrice
				skuElement = domain.AlibabaRetailMarketingItemdiscountActivitySkuAddSkuActivityElementDto{
					SkuCode:       utils.String2Pointer(utils.Int2Str(v.SkuID)),
					FixPriceMoney: &fixPriceMoney,
					//Limit: &domain.AlibabaRetailMarketingItemdiscountActivitySkuAddLimitDto{
					//	OrderLimitCnt: &limitCount,
					//},
				}
			case tao_vegetable.DiscountTypeDiscounts:
				discountRate = int64(v.PricePercentage * 10)
				skuElement = domain.AlibabaRetailMarketingItemdiscountActivitySkuAddSkuActivityElementDto{
					SkuCode:      utils.String2Pointer(utils.Int2Str(v.SkuID)),
					DiscountRate: &discountRate,
					//Limit: &domain.AlibabaRetailMarketingItemdiscountActivitySkuAddLimitDto{
					//	OrderLimitCnt: &limitCount,
					//},
				}
			}
			skuElements = append(skuElements, skuElement)
			actData.SkuElements = &skuElements
		}
	}
	return actData
}

//删除活动详情
func storeSku2ActData4Delete(actStoreSku []*model.ActStoreSku2, handler func(int8) bool) (actIDList []string) {
	for _, v := range actStoreSku {
		if handler == nil || handler(v.SyncStatus) {
			if v.VendorActID != "" {
				actIDList = append(actIDList, v.VendorActID)
			}
		}
	}
	return actIDList
}

//删除活动的商品详情
func actSku2Delete(actIDs []string, vendorOrgCode, vendorStoreID string) (map[string]domain.AlibabaRetailMarketingItemdiscountActivitySkuDeleteItemDiscountActivityElementOperateRequest, error) {
	var (
		SkuElement []domain.AlibabaRetailMarketingItemdiscountActivitySkuDeleteSkuActivityElementDto
		deData     = make(map[string]domain.AlibabaRetailMarketingItemdiscountActivitySkuDeleteItemDiscountActivityElementOperateRequest, 0)
	)
	for _, v := range actIDs {
		i := utils.Str2Int64(v)
		if skus, err := getAPI(vendorOrgCode, 0, vendorStoreID).ActivitySkuQuery(i); err == nil {
			//查询商品
			for _, sku := range skus {
				SkuElement = append(SkuElement, domain.AlibabaRetailMarketingItemdiscountActivitySkuDeleteSkuActivityElementDto{
					SkuCode: sku.SkuCode,
				})
			}
			//查询活动详情
			act, err := getAPI(vendorOrgCode, 0, vendorStoreID).ActivityQuery(i, "")
			if err != nil {
				return nil, err
			}
			deData[v] = domain.AlibabaRetailMarketingItemdiscountActivitySkuDeleteItemDiscountActivityElementOperateRequest{
				SkuElements: &SkuElement,
				ActId:       &i,
				CreatorId:   act.CreatorId,
				CreatorName: act.CreatorName,
			}
		}
	}
	return deData, nil
}

func isCreateOrUpdate(syncStatus int8) bool {
	return model.IsSyncStatusNeedCreate(syncStatus) || model.IsSyncStatusNeedUpdate(syncStatus)
}

func createOneShopAct(act *model.Act2, vendorStoreID string, actStoreSku []*model.ActStoreSku2) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	//1 活动详情
	actData := act2TxdActivity(act)
	//2 活动商品详情
	actSkuData := storeSku2ActData(act, actStoreSku, isCreateOrUpdate)
	globals.SugarLogger.Debugf("createOneShopAct actData=%s,actSkuData=%s", utils.Format4Output(actData, false), utils.Format4Output(actSkuData, false))
	if actData != nil && actSkuData != nil {
		if globals.EnableMtwmStoreWrite {
			//创建活动
			actData.StoreIds = &[]string{vendorStoreID}
			actID, err1 := getAPI(act.VendorOrgCode, 0, vendorStoreID).ActivityCreate(*actData)
			if err1 != nil || actID == 0 {
				failedList = append(failedList, &partner.StoreSkuInfoWithErr{
					VendoreID: model.VendorIDTaoVegetable,
					ErrMsg:    fmt.Sprintf("%v", err1),
					StoreID:   int(utils.Str2Int64WithDefault(vendorStoreID, 0)),
				})
				return failedList, err1
			}
			//活动增加商品
			actSkuData.ActId = &actID
			err3, successSkuCode, failSkuCode := getAPI(act.VendorOrgCode, 0, vendorStoreID).ActivitySkuCreate(*actSkuData)
			err = err3
			if err != nil { //商品新增失败，回滚删除创建的活动
				if err4 := getAPI(act.VendorOrgCode, 0, vendorStoreID).ActivityDelete(*actData.CreatorId, *actData.CreatorName, actID); err != nil {
					return nil, fmt.Errorf("活动创建但新增商品失败，删除活动错误：%v，请在淘鲜达平台删除此活动", err4)
				}
			}
			actStoreSkuMap := make(map[int]*model.ActStoreSku2)
			for _, v := range actStoreSku {
				actStoreSkuMap[v.SkuID] = v
			}

			for _, v := range successSkuCode.SkuID {
				if v2 := actStoreSkuMap[int(utils.Str2Int64WithDefault(v, 0))]; v2 != nil {
					v2.VendorActID = utils.Int64ToStr(successSkuCode.ActID)
				}
			}

			for _, v := range failSkuCode {
				if v2 := actStoreSkuMap[int(utils.Str2Int64WithDefault(v, 0))]; v2 != nil {
					failedList = append(failedList, &partner.StoreSkuInfoWithErr{
						StoreSkuInfo: &partner.StoreSkuInfo{
							SkuID: v2.SkuID,
						},
						VendoreID: model.VendorIDTaoVegetable,
						StoreID:   int(utils.Str2Int64WithDefault(vendorStoreID, 0)),
						ErrMsg:    fmt.Sprint(err3),
					})
				}
			}
		}
	}
	return failedList, err
}

func cancelOneShopAct(act *model.Act2, vendorStoreID string, actStoreSku []*model.ActStoreSku2) (failedList []*partner.StoreSkuInfoWithErr, err error) {
	if list := storeSku2ActData4Delete(actStoreSku, nil /*model.IsSyncStatusNeedDelete*/); len(list) > 0 {
		if globals.EnableMtwmStoreWrite {
			actStoreSkuMap := make(map[string]*model.ActStoreSku2)
			for _, v := range actStoreSku {
				actStoreSkuMap[v.VendorActID] = v
			}
			//查找删除的活动商品
			sku2Delete, err := actSku2Delete(list, act.VendorOrgCode, vendorStoreID)
			if err != nil {
				return nil, err
			}
			//删除活动以及商品
			for k, v := range sku2Delete {
				if err = getAPI(act.VendorOrgCode, 0, vendorStoreID).ActivitySkuDelete(v); err == nil {
					err = getAPI(act.VendorOrgCode, 0, vendorStoreID).ActivityDelete(*v.CreatorId, *v.CreatorName, utils.Str2Int64(k))
				}
				if err != nil {
					failedList = append(failedList, &partner.StoreSkuInfoWithErr{
						StoreSkuInfo: &partner.StoreSkuInfo{
							SkuID: actStoreSkuMap[k].SkuID,
						},
						StoreID:   int(utils.Str2Int64WithDefault(vendorStoreID, 0)),
						ErrMsg:    fmt.Sprint(err),
						VendoreID: model.VendorIDTaoVegetable,
					})
				}
			}

			err = nil // 强制不返回错误，使用部分错误
		}
	}
	return failedList, err
}

func getActStoreSkuFromTaskResult(taskReslt []interface{}) (list []*model.ActStoreSku2) {
	for _, v := range taskReslt {
		actStoreSkuList := v.([]*model.ActStoreSku2)
		list = append(list, actStoreSkuList...)
	}
	return list
}

func createSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2) (createdList []*model.ActStoreSku2, err error) {
	actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
	task := tasksch.NewParallelTask("txd createSkuAct", nil, ctx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			list := batchItemList[0].([]*model.ActStoreSku2)
			failedList, err2 := createOneShopAct(act, list[0].VendorStoreID, list)
			if err = err2; err2 == nil {
				if len(failedList) > 0 {
					failedMap := putils.StoreSkuInfoWithErrList2MapBySku(failedList)
					list = []*model.ActStoreSku2{}
					for _, v := range actStoreSku {
						if failedMap[v.SkuID] == nil {
							list = append(list, v)
						}
					}
					list = []*model.ActStoreSku2{}
				}
				retVal = []interface{}{list}
			}
			return retVal, err
		}, actStoreSkuListList)
	tasksch.HandleTask(task, parentTask, true).Run()
	result, err := task.GetResult(0)
	return getActStoreSkuFromTaskResult(result), err
}

func cancelSkuAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2) (canceledList []*model.ActStoreSku2, err error) {
	actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
	task := tasksch.NewParallelTask("txd cancelSkuAct", nil, ctx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			actStoreSkuList := batchItemList[0].([]*model.ActStoreSku2)
			if _, err = cancelOneShopAct(act, actStoreSkuList[0].VendorStoreID, actStoreSkuList); err == nil {
				retVal = []interface{}{actStoreSkuList}
			}
			return retVal, err
		}, actStoreSkuListList)
	tasksch.HandleTask(task, parentTask, true).Run()
	result, err := task.GetResult(0)
	return getActStoreSkuFromTaskResult(result), err
}

func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
	var actStoreSkuList4Create, actStoreSkuList4Delete []*model.ActStoreSku2
	var updateItems []*dao.KVUpdateItem

	actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuList)
	for storeID := range actStoreSkuMap {
		for _, actStoreSku := range actStoreSkuMap[storeID] {
			if model.IsSyncStatusDelete(actStoreSku.SyncStatus) {
				actStoreSkuList4Delete = append(actStoreSkuList4Delete, actStoreSku)
			} else if model.IsSyncStatusNew(actStoreSku.SyncStatus) {
				actStoreSkuList4Create = append(actStoreSkuList4Create, actStoreSku)
			}
		}
	}
	err = func() (err error) {
		if model.IsSyncStatusDelete(act.SyncStatus) {
			canceledList, err2 := cancelSkuAct(ctx, nil, act, actStoreSkuList)
			updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, canceledList, model.SyncFlagModifiedMask)...)
			if err = err2; err == nil {
				updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
			}
		} else if model.IsSyncStatusNew(act.SyncStatus) {
			createdList, err2 := createSkuAct(ctx, nil, act, actStoreSkuList4Create)
			updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, createdList, model.SyncFlagNewMask)...)
			if err = err2; err == nil {
				updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagNewMask))
			}
		} else if model.IsSyncStatusUpdate(act.SyncStatus) {
			if len(actStoreSkuList4Create) > 0 {
				addedList, err2 := createSkuAct(ctx, nil, act, actStoreSkuList4Create)
				updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, addedList, model.SyncFlagNewMask)...)
				if err = err2; err != nil {
					return err
				}
			}
			if len(actStoreSkuList4Delete) > 0 {
				deletedList, err2 := cancelSkuAct(ctx, nil, act, actStoreSkuList4Delete)
				updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, deletedList, model.SyncFlagDeletedMask)...)
				if err = err2; err != nil {
					return err
				}
			}
			if err == nil {
				updateItems = append(updateItems, partner.Act2Update(ctx, act, model.SyncFlagModifiedMask))
			}
		}
		return err
	}()
	db := dao.GetDB()
	_, err2 := dao.BatchUpdateActEntity(db, model.IsSyncStatusDelete(act.SyncStatus), updateItems)
	if err == nil {
		err = err2
	}
	return err
}

func (c *PurchaseHandler) GetActAmple(ctx *jxcontext.Context, vendorStoreID, vendorOrgCode string) (ample int, err error) {
	//for _, v := range mtwmapi.ActTypeList {
	//	//1表示进行中
	//	if actList, err := getAPI(vendorOrgCode, 0, vendorStoreID).GetByAppPoiCodeAndType(vendorOrgCode, 1, v); err == nil {
	//		ample += len(actList)
	//	}
	//}
	return ample, err
}
