package jdapi

import (
	"crypto/md5"
	"fmt"
	"time"

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

const (
	KeyStationNo      = "stationNo"
	KeyOutStationNo   = "outStationNo"
	KeyPromotionPrice = "promotionPrice"
	KeyLimitSkuCount  = "limitSkuCount"

	KeyInfoId    = "infoId"
	KeyOutInfoId = "outInfoId"
)

const (
	MaxPromotionSkuCount = 200
)

const (
	PromotionStateNotConfirm = 1 // 未确认
	PromotionStateConfirmed  = 5 // 已确认
	PromotionStateCanceled   = 6 // 已取消
	PromotionStateEnded      = 9 // 已结束
)

type PromotionSku struct {
	SkuID        int64  `json:"skuId,omitempty"`
	OutSkuID     string `json:"outSkuId,omitempty"`
	StationNo    int64  `json:"stationNo,omitempty"`
	OutStationNo string `json:"outStationNo,omitempty"`

	PromotionPrice int64  `json:"promotionPrice,omitempty"`
	LimitSkuCount  int    `json:"limitSkuCount,omitempty"`
	FailReason     string `json:"failReason,omitempty"`
}

func getPromotionCmd(inCmd string, promotionType int) (outCmd string) {
	if promotionType == PromotionTypeDirectDown {
		if inCmd == "adjustPromotionSku" || inCmd == "adjustPromotionTime" {
			outCmd = "promotesku/" + inCmd
		} else {
			outCmd = "singlePromote/" + inCmd
		}
	} else if promotionType == PromotionTypeLimitedTime {
		outCmd = "limitTime/" + inCmd
	} else {
		panic("unknow promotionType!")
	}
	return outCmd
}

// 单品直降添加主活动信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=ee8685c9be9b4aa5bdc41468c5ebc33b
func (a *API) CreatePromotionInfosSingle(name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
	return a.createPromotionInfos(PromotionTypeDirectDown, name, beginDate, endDate, outInfoId, advertising, traceId)
}

// 单品直降添加活动规则信息接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=900a9577cb304bbbb59abb7c2c33854d
func (a *API) CreatePromotionRulesSingle(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
	return a.createPromotionRules(PromotionTypeDirectDown, infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
}

// 单品直降添加活动商品信息接口
// 最多200条
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=0ad0715e0aaa42489cbeac36398e916d
func (a *API) CreatePromotionSkuSingle(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
	return a.createPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus, traceId)
}

// 单品直降活动提交保存接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=b84e14eb341e470db8ed9b60f78edb16
func (a *API) ConfirmPromotionSingle(infoId int64, outInfoId, traceId string) (err error) {
	return a.confirmPromotion(PromotionTypeDirectDown, infoId, outInfoId, traceId)
}

// 单品直降活动部分商品取消接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=cfd14470b3fe4625bd2405b20bf8cec4
func (a *API) CancelPromotionSkuSingle(infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
	return a.cancelPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, cancelSkus, traceId)
}

// 单品直降整个活动取消接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=3d02c2acad714bea86d20d498a1aa074
func (a *API) CancelPromotionSingle(infoId int64, outInfoId, traceId string) (err error) {
	return a.cancelPromotion(PromotionTypeDirectDown, infoId, outInfoId, traceId)
}

// 单品实时促销活动结束时间调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=0abab0c4b81d45e5bc555cc7dfbeb1ad
func (a *API) AdjustPromotionTimeSingle(infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
	return a.adjustPromotionTime(PromotionTypeDirectDown, infoId, outInfoId, endDate, traceId)
}

// 单品实时促销商品促销数量调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=82964e5e0f9c448db072a54ed20e00c4
func (a *API) AdjustPromotionSkuSingle(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
	return a.adjustPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus, traceId)
}

// 以下为限时抢

// 限时抢添加活动主信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=7d8b7ff86c9e457bb8a46963cb575769
func (a *API) CreatePromotionInfosLimitTime(name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
	return a.createPromotionInfos(PromotionTypeLimitedTime, name, beginDate, endDate, outInfoId, advertising, traceId)
}

// 限时抢添加活动规则信息接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=e80674791d3542f0a87502753c0d0592
func (a *API) CreatePromotionRulesLimitTime(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
	return a.createPromotionRules(PromotionTypeLimitedTime, infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
}

// 限时抢添加活动商品信息接口
// 最多200条
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=65fecef4883c40c6b23bbdb6123f5d80
func (a *API) CreatePromotionSkuLimitTime(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
	return a.createPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus, traceId)
}

// 限时抢活动提交保存接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=3991063e2f0d435094e9fe44754f3490
func (a *API) ConfirmPromotionLimitTime(infoId int64, outInfoId, traceId string) (err error) {
	return a.confirmPromotion(PromotionTypeLimitedTime, infoId, outInfoId, traceId)
}

// 限时抢活动取消部分商品接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=01bd37df882749af91be4b040873ccc6
func (a *API) CancelPromotionSkuLimitTime(infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
	return a.cancelPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, cancelSkus, traceId)
}

// 限时抢整个活动取消接口
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=97b6678d30624f73bc13cb68987e6a6d
func (a *API) CancelPromotionLimitTime(infoId int64, outInfoId, traceId string) (err error) {
	return a.cancelPromotion(PromotionTypeLimitedTime, infoId, outInfoId, traceId)
}

// 限时抢活动结束时间调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=f91035295cd54a9bbd2db9dfc800484c
func (a *API) AdjustPromotionTimeLimitTime(infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
	return a.adjustPromotionTime(PromotionTypeLimitedTime, infoId, outInfoId, endDate, traceId)
}

// 限时抢商品促销数量调整接口
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=aa878a000dfb4a248634ee755af1f1d3
func (a *API) AdjustPromotionSkuLimitTime(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
	return a.adjustPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus, traceId)
}

func (a *API) createPromotionInfos(promotionType int, name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
	if outInfoId == "" {
		outInfoId = fmt.Sprintf("%X", md5.Sum([]byte(name)))
	}
	jdParams := getCommonSkuPromotionParams(0, outInfoId, traceId)
	jdParams["promotionName"] = name
	jdParams["beginDate"] = utils.Time2Str(beginDate)
	jdParams["endDate"] = utils.Time2Str(endDate)
	jdParams["advertising"] = advertising
	jdParams["promotionType"] = promotionType
	jdParams["advertising"] = advertising
	result, err := a.AccessAPINoPage(getPromotionCmd("createPromotionInfos", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "0"))
	if err == nil {
		return utils.MustInterface2Int64(result), nil
	}
	return 0, err
}

func (a *API) createPromotionRules(promotionType int, infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
	jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
	jdParams["limitDevice"] = limitDevice
	jdParams["limitPin"] = limitPin
	jdParams["limitCount"] = limitCount
	jdParams["limitDaily"] = limitDaily
	_, err = a.AccessAPINoPage(getPromotionCmd("createPromotionRules", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
	return err
}

// todo skusResult 返回值没有意义，为了兼容暂时保留
// 此接口在活动确认后不能调用
func (a *API) createPromotionSku(promotionType int, infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
	jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
	jdParams["skus"] = skus
	// todo 当前是在出错时，把data中的数据当成错误信息处理的
	result, err := a.AccessAPINoPage(getPromotionCmd("createPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
	if err == nil && result != nil {
		err = JdMap2StructByJson(result, &skusResult, false)
	}
	return skusResult, err
}

func (a *API) confirmPromotion(promotionType int, infoId int64, outInfoId, traceId string) (err error) {
	jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
	_, err = a.AccessAPINoPage(getPromotionCmd("confirmPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
	return err
}

// 与createPromotionSku不同的是，此接口在活动确认后可以调用，实时生效
func (a *API) cancelPromotionSku(promotionType int, infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
	jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
	jdParams["cancelSkus"] = cancelSkus
	_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
	return err
}

// 取消一个不存在的活动，不会报错
func (a *API) cancelPromotion(promotionType int, infoId int64, outInfoId, traceId string) (err error) {
	jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
	_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
	return err
}

func (a *API) adjustPromotionTime(promotionType int, infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
	jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
	_, err = a.AccessAPINoPage(getPromotionCmd("adjustPromotionTime", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
	return err
}

func (a *API) adjustPromotionSku(promotionType int, infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
	jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
	jdParams["skus"] = skus
	result, err := a.AccessAPINoPage(getPromotionCmd("adjustPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
	if err == nil && result != nil {
		err = JdMap2StructByJson(result, &skusResult, false)
	}
	return skusResult, err
}

func getCommonSkuPromotionParams(infoId int64, outInfoId, traceId string) map[string]interface{} {
	jdParams := map[string]interface{}{
		"timeStamp": utils.GetCurTimeStr(),
	}
	if infoId != 0 {
		jdParams[KeyInfoId] = infoId
	} else {
		jdParams[KeyOutInfoId] = outInfoId
	}
	if traceId != "" {
		jdParams["traceId"] = traceId
	}
	return jdParams
}
