package ebai

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

func actType2Ebai(actType int) int {
	if actType < model.ActOrderBegin {
		return ebaiapi.ActivityTypeDirectDown
	}
	return ebaiapi.ActivityTypeFullDiscount
}

func actOrderRules2Ebai(actOrderRules []*model.ActOrderRule) (ebaiRules []*ebaiapi.ActivityRule) {
	for _, v := range actOrderRules {
		ebaiRules = append(ebaiRules, &ebaiapi.ActivityRule{
			Accords: int(jxutils.IntPrice2Standard(v.SalePrice)),
			Sale:    int(jxutils.IntPrice2Standard(v.DeductPrice)),
		})
	}
	return ebaiRules
}

func actStoreSu2Ebai4Add(oneStoreActSku []*model.ActStoreSku2) (skus []*ebaiapi.ActivitySkuInfo4Add) {
	for _, v := range oneStoreActSku {
		if v.VendorSkuID != "" {
			if model.IsSyncStatusNeedCreate(v.SyncStatus) {
				skus = append(skus, &ebaiapi.ActivitySkuInfo4Add{
					SkuID:        v.VendorSkuID,
					SpecialPrice: v.ActualActPrice,
					Stock:        v.Stock,
				})
			}
		}
	}
	return skus
}

func actStoreSu2Ebai4Update(oneStoreActSku []*model.ActStoreSku2) (skus []*ebaiapi.ActivitySkuInfo4Update) {
	for _, v := range oneStoreActSku {
		if v.VendorSkuID != "" {
			if model.IsSyncStatusNeedUpdate(v.SyncStatus) {
				skus = append(skus, &ebaiapi.ActivitySkuInfo4Update{
					ShopID:       utils.Int2Str(v.StoreID),
					SkuID:        v.VendorSkuID,
					SpecialPrice: v.ActPrice,
					Stock:        v.Stock,
				})
			}
		}
	}
	return skus
}

func actStoreSu2Ebai4Delete(oneStoreActSku []*model.ActStoreSku2) (skus []string) {
	for _, v := range oneStoreActSku {
		if v.VendorSkuID != "" {
			if model.IsSyncStatusNeedDelete(v.SyncStatus) {
				skus = append(skus, v.VendorSkuID)
			}
		}
	}
	return skus
}

func act2EbaiActivity(act *model.Act2, actOrderRules []*model.ActOrderRule) (activity *ebaiapi.ActivityInfo) {
	activity = &ebaiapi.ActivityInfo{
		ActivityName:     utils.LimitMixedStringLen(act.GetRealActName(), ebaiapi.MaxActivityNameLength),
		ActivityType:     actType2Ebai(act.Type),
		StartTime:        act.BeginAt.Unix(),
		EndTime:          act.EndAt.Unix(),
		OpenTime:         "00:00",
		CloseTime:        "23:59",
		WeekDay:          "0,1,2,3,4,5,6",
		ActivityDesc:     act.Advertising,
		ShowCategory:     model.ActTypeName[act.Type],
		PromotionSkuDesc: utils.LimitMixedStringLen(act.Advertising, ebaiapi.MaxActivityDescLength),
		DayLimit:         1,
		ActivityPlatform: ebaiapi.ActivityPFAll,
	}
	if act.LimitCount > 0 {
		activity.OrderLimit = act.LimitCount
	}
	if activity.DayLimit == 0 {
		activity.DayLimit = 999
	}
	if actOrderRules != nil {
		activity.Rule = actOrderRules2Ebai(actOrderRules)
	}
	return activity
}

func createOneShopAct(act *model.Act2, shopID string, oneStoreActSku []*model.ActStoreSku2) (ebaiActIDStr string, err error) {
	activity := act2EbaiActivity(act, nil)
	if globals.EnableEbaiStoreWrite {
		ebaiActID, err2 := api.EbaiAPI.ActivityCreate(shopID, 0, 0, activity)
		if err = err2; err == nil {
			ebaiActIDStr = utils.Int64ToStr(ebaiActID)
			if _, err = ActivitySkuAddBatch(ebaiActID, shopID, 0, activity.ActivityType, actStoreSu2Ebai4Add(oneStoreActSku), false); err != nil {
				ActivityDisable(ebaiActID, shopID, 0, 0)
			}
		}
	} else {
		ebaiActIDStr = utils.Int64ToStr(jxutils.GenFakeID())
	}
	return ebaiActIDStr, err
}

func ActivitySkuAddBatch(activityID int64, shopID string, baiduShopID int64, activityType int, skuList []*ebaiapi.ActivitySkuInfo4Add, isSkuIDCustom bool) (successIDs []string, err error) {
	if globals.EnableEbaiStoreWrite {
		successIDs, err = api.EbaiAPI.ActivitySkuAddBatch(activityID, shopID, baiduShopID, activityType, skuList, isSkuIDCustom)
	} else {
		for _, v := range skuList {
			successIDs = append(successIDs, v.SkuID)
		}
	}
	return successIDs, err
}

func ActivitySkuDeleteBatch(activityID int64, shopID string, baiduShopID int64, skuIDs []string, isSkuIDCustom bool) (successIDs []string, err error) {
	if globals.EnableEbaiStoreWrite {
		successIDs, err = api.EbaiAPI.ActivitySkuDeleteBatch(activityID, shopID, baiduShopID, skuIDs, isSkuIDCustom)
	} else {
		successIDs = append([]string{}, skuIDs...)
	}
	return successIDs, err
}

func ActivitySkuUpdateBatch(activityID int64, actSkuInfoList []*ebaiapi.ActivitySkuInfo4Update) (faildInfoList []string, err error) {
	if globals.EnableEbaiStoreWrite {
		faildInfoList, err = api.EbaiAPI.ActivitySkuUpdateBatch(activityID, actSkuInfoList)
	}
	return faildInfoList, err
}

func ActivityDisable(activityID int64, shopID string, baiduShopID, supplierID int64) (err error) {
	if globals.EnableEbaiStoreWrite {
		err = api.EbaiAPI.ActivityDisable(activityID, shopID, baiduShopID, supplierID)
	}
	return 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("ebai createSkuAct", nil, ctx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			list := batchItemList[0].([]*model.ActStoreSku2)
			var vendorActID string
			if vendorActID, err = createOneShopAct(act, utils.Int2Str(list[0].StoreID), list); err == nil {
				for _, v := range list {
					v.VendorActID = vendorActID
				}
				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, actStoreSkuMap map[string][]*model.ActStoreSku2) (canceledList []*model.ActStoreSku2, err error) {
	var vendorActIDs []string
	for k := range actStoreSkuMap {
		vendorActIDs = append(vendorActIDs, k)
	}
	task := tasksch.NewParallelTask("ebai cancelSkuAct", nil, ctx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			vendorActID := batchItemList[0].(string)
			actStoreSkuList := actStoreSkuMap[vendorActID]
			if vendorActID != "" {
				err = ActivityDisable(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, 0)
			}
			if err == nil {
				retVal = []interface{}{actStoreSkuList}
			}
			return retVal, err
		}, vendorActIDs)
	tasksch.HandleTask(task, parentTask, true).Run()
	result, err := task.GetResult(0)
	return getActStoreSkuFromTaskResult(result), err
}

func deleteSkuActSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, actStoreSkuMap, vendorActInfoMap map[string][]*model.ActStoreSku2) (deletedList []*model.ActStoreSku2, err error) {
	var vendorActIDs []string
	for k := range actStoreSkuMap {
		if k != "" {
			vendorActIDs = append(vendorActIDs, k)
		}
	}
	if len(vendorActIDs) > 0 {
		task := tasksch.NewParallelTask("ebai deleteSkuAct", nil, ctx,
			func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
				vendorActID := batchItemList[0].(string)
				actStoreSkuList := actStoreSkuMap[vendorActID]
				vendorActStoreSkuList := vendorActInfoMap[vendorActID]
				if len(actStoreSkuList) < len(vendorActStoreSkuList) {
					if list := actStoreSu2Ebai4Delete(actStoreSkuList); len(list) > 0 {
						_, err = ActivitySkuDeleteBatch(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, list, false)
					}
				} else {
					err = ActivityDisable(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, 0)
				}
				if err == nil {
					retVal = []interface{}{actStoreSkuList}
				}
				return retVal, err
			}, vendorActIDs)
		tasksch.HandleTask(task, parentTask, true).Run()
		result, err2 := task.GetResult(0)
		err = err2
		deletedList = getActStoreSkuFromTaskResult(result)
	}
	return deletedList, err
}

func addSkuActSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actStoreSku []*model.ActStoreSku2, vendorActIDMap map[int]string) (addedList []*model.ActStoreSku2, err error) {
	actStoreSkuListList := partner.SplitActStoreSku2List(actStoreSku)
	if len(actStoreSkuListList) > 0 {
		task := tasksch.NewParallelTask("ebai addSkuActSkus", nil, ctx,
			func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
				actStoreSkuList := batchItemList[0].([]*model.ActStoreSku2)
				vendorActID := vendorActIDMap[actStoreSkuList[0].StoreID]
				if vendorActID != "" {
					if list := actStoreSu2Ebai4Add(actStoreSkuList); len(list) > 0 {
						_, err = ActivitySkuAddBatch(utils.Str2Int64(vendorActID), utils.Int2Str(actStoreSkuList[0].StoreID), 0, actType2Ebai(act.Type), list, false)
					}
				} else {
					vendorActID, err = createOneShopAct(act, utils.Int2Str(actStoreSkuList[0].StoreID), actStoreSkuList)
				}
				if err == nil {
					for _, v := range actStoreSkuList {
						v.VendorActID = vendorActID
					}
					retVal = []interface{}{actStoreSkuList}
				}
				return retVal, err
			}, actStoreSkuListList)
		tasksch.HandleTask(task, parentTask, true).Run()
		result, err2 := task.GetResult(0)
		err = err2
		addedList = getActStoreSkuFromTaskResult(result)
	}
	return addedList, err
}

func (c *PurchaseHandler) SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, act *model.Act2, actOrderRules []*model.ActOrderRule, actStoreSkuList []*model.ActStoreSku2) (err error) {
	vendorActInfoMap := make(map[string][]*model.ActStoreSku2)
	deleteActInfoMap := make(map[string][]*model.ActStoreSku2)
	vendorActIDMap := make(map[int]string)
	var actStoreSkuList4Create []*model.ActStoreSku2
	var updateItems []*dao.KVUpdateItem

	actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuList)
	for storeID := range actStoreSkuMap {
		for _, actStoreSku := range actStoreSkuMap[storeID] {
			vendorActInfoMap[actStoreSku.VendorActID] = append(vendorActInfoMap[actStoreSku.VendorActID], actStoreSku)
			if vendorActIDMap[storeID] == "" && actStoreSku.VendorActID != "" {
				vendorActIDMap[storeID] = actStoreSku.VendorActID
			}
			if model.IsSyncStatusDelete(actStoreSku.SyncStatus) {
				vendorActID := actStoreSku.VendorActID
				if vendorActID == "" {
					vendorActID = act.VendorActID
				}
				deleteActInfoMap[vendorActID] = append(deleteActInfoMap[vendorActID], 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, vendorActInfoMap)
			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 := addSkuActSkus(ctx, nil, act, actStoreSkuList4Create, vendorActIDMap)
				updateItems = append(updateItems, partner.ActStoreSku2Update(ctx, addedList, model.SyncFlagNewMask)...)
				if err = err2; err != nil {
					return err
				}
			}
			if len(deleteActInfoMap) > 0 {
				deletedList, err2 := deleteSkuActSkus(ctx, nil, deleteActInfoMap, vendorActInfoMap)
				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 ebaiapi.ActivityTypeList {
		if actIDs, err := api.EbaiAPI.ActMultiChannelQueryIDs("", utils.Str2Int64(vendorStoreID), v); err == nil && len(actIDs) > 0 {
			ample++
		}
	}
	return ample, err
}
