package partner

import (
	"errors"
	"fmt"
	"time"

	"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"
)

const (
	StoreNameSeparator = "-"
)

const (
	CreatedPeration = "create"
	UpdatedPeration = "update"
)

const (
	CancelWaybillReasonNotAcceptIntime   = 1
	CancelWaybillReasonSwitch2SelfFailed = 2
	CancelWaybillReasonOther             = 10
	CancelWaybillReasonDYPSCancel        = 11 //抖音门店转自送，取消自动运力
)

const (
	AfsApproveTypeRefund               = 1 // 同意退款
	AfsApproveTypeReturnGoods          = 2 // 退货退款
	AfsApproveTypeRefused              = 3 // 驳回退款
	AfsApproveTypeRefusedToRefundMoney = 4 // 退货转退款
)

const (
	TimerTypeNoOverride         = 0 // GetStatusActionConfig 返回表示不修改缺省配置
	TimerTypeByPass             = 1
	TimerTypeBaseNow            = 2
	TimerTypeBaseStatusTime     = 3
	TimerTypeBaseOrderCreatedAt = 4
)

type StatusActionParams struct {
	TimerType  int           // 参见上面的相关常量定义
	Timeout    time.Duration // 超时时间，0在GetStatusActionConfig返回时表示不修改缺省
	TimeoutGap int           // 以秒为单位的随机时间，0在GetStatusActionConfig返回时表示不修改缺省
}

type OrderInFoChange struct {
}

func (s *StatusActionParams) GetRefTimeout(statusTime time.Time, orderCreatedAt time.Time) (timeout time.Duration) {
	switch s.TimerType {
	case TimerTypeBaseNow:
		timeout = s.Timeout
	case TimerTypeBaseStatusTime:
		timeout = statusTime.Sub(time.Now()) + s.Timeout
	case TimerTypeBaseOrderCreatedAt:
		timeout = orderCreatedAt.Sub(time.Now()) + s.Timeout
	default:
		timeout = 0
	}
	if timeout < 0 {
		timeout = 0
	}
	return timeout
}

var (
	CancelWaybillReasonStrNotAcceptIntime      = "没有及时抢单"
	CancelWaybillReasonStrSwitch2SelfFailed    = "转自送失败"
	CancelWaybillReasonStrOrderAlreadyFinished = "订单已经结束"
	CancelWaybillReasonStrActive               = "操作由人员主动发起"
	CancelWaybillReasonNotInStoreOpenTime      = "不在门店的营业时间范围内"
	CancelWaybillReasonStrDYPSCancel           = "抖音门店转自送，取消自动运力"
)

var (
	ErrCanNotFindItem     = errors.New("没有找到指定的东西")
	ErrStoreHaveNoCourier = errors.New("门店没有绑定相应的配送信息")
)

var (
	CurOrderManager IOrderManager
	CurStoreManager IStoreManager

	PurchasePlatformHandlers map[int]IPurchasePlatformHandler
	PurchaseOrderHandlers    map[int]IPurchasePlatformOrderHandler
)

type IOrderManager interface {
	SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao.DaoDB) (isDuplicated bool, err error)

	OnOrderNew(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error)
	OnOrderAdjust(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error)
	OnOrderStatusChanged(vendorOrgCode string, orderStatus *model.OrderStatus) (err error)
	OnOrderMsg(order *model.GoodsOrder, vendorStatus, remark string) (err error)

	OnWaybillStatusChanged(bill *model.Waybill) (err error)

	CreateAfsOrderFromOrder(vendorOrderID string, vendorID int) (afsOrder *model.AfsOrder, err error)
	LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error)
	LoadOrder2(vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error)

	LoadOrderFinancial(vendorOrderID string, vendorID int) (order *model.OrderFinancial, err error)
	LoadOrderFinancial2(vendorOrderID2 string, vendorID int) (order *model.OrderFinancial, err error)

	UpdateOrderStatusAndDeliveryFlag(order *model.GoodsOrder) (err error)
	UpdateOrderFields(order *model.GoodsOrder, fieldList []string) (err error)
	LoadStoreDetail(storeID, vendorID int) (storeDetail *dao.StoreDetail, err error)

	LoadWaybill(vendorWaybillID string, waybillVendorID int) (bill *model.Waybill, err error)
	OnOrderComments(orderCommentList []*model.OrderComment) (err error)

	SaveOrderFinancialInfo(order *model.OrderFinancial, operation string) (err error)
	SaveAfsOrderFinancialInfo(afsOrder *model.AfsOrder) (err error)

	GetOrderWaybillInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isNotEnded, isGetPos bool) (bills []*model.WaybillExt, err error)

	ChangeOrderInfo(order *model.GoodsOrder) (err error)
	// afs order
	OnAfsOrderAdjust(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error)
	OnAfsOrderNew(afsOrder *model.AfsOrder, orderStatus *model.OrderStatus) (err error)
	OnAfsOrderStatusChanged(orderStatus *model.OrderStatus) (err error)
	LoadAfsOrder(vendorAfsOrderID string, vendorID int) (afsOrder *model.AfsOrder, err error)
	UpdateAfsOrderFields(afsOrder *model.AfsOrder, fieldList []string) (err error)

	GetStatusDuplicatedCount(status *model.OrderStatus) (duplicatedCount int)
}

type IStoreManager interface {
	OnStoreStatusChanged(vendorStoreID string, vendorID int, storeStatus int) (err error)
	OnCourierStoreStatusChanged(ctx *jxcontext.Context, vendorStoreID string, vendorID int, auditStatus int, message string) (err error)
}

// purchase handler中
// 所有Sync，Refresh开头的函数都必须自己清理sync_status标记
// 所有非以Sync，Refresh开头的函数不用自己清理sync_status标记（VendorSync统一处理）

type IPurchasePlatformHandler interface {
	IPurchasePlatformActHandler
	IPurchasePlatformOrderHandler

	GetVendorID() int

	// 只与平台相关
	GetVendorCategories(ctx *jxcontext.Context) (vendorCats []*model.SkuVendorCategory, err error)

	// Store
	ReadStore(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorStoreName string) (store *dao.StoreDetail, err error)
	UpdateStore(db *dao.DaoDB, storeID int, userName string) (err error)
	CreateStore2(db *dao.DaoDB, storeID int, userName string, params map[string]interface{}, storeDetail *dao.StoreDetail) (vendorStoreID string, err error)
	DeleteStore(db *dao.DaoDB, storeID int, userName string) (err error)
	GetStoreStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string) (storeStatus int, err error)
	UpdateStoreCustomID(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID string, storeID int64) (err error)

	RefreshAllStoresID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error)

	UploadImg(ctx *jxcontext.Context, vendorOrgCode, imgURL string, imgData []byte, imgName string, imgType int) (imgHint string, err error)
	UpdateStoreLineStatus(ctx *jxcontext.Context, vendorOrgCode string, storeID int, vendorStoreID string, lineStatus int) (err error)
}

// db *dao.DaoDB,
type IMultipleStoresHandler interface {
	IPurchasePlatformHandler
	GetAllCategories(ctx *jxcontext.Context, vendorOrgCode string) (cats []*BareCategoryInfo, err error)

	// CreateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) (err error)
	// UpdateCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
	// DeleteCategory(db *dao.DaoDB, cat *model.SkuCategory, userName string) error
	// ReorderCategories(db *dao.DaoDB, parentCatID int, userName string) (err error)

	CreateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error)
	UpdateCategory2(ctx *jxcontext.Context, cat *dao.SkuStoreCatInfo) (err error)
	DeleteCategory2(ctx *jxcontext.Context, vendorOrgCode, vendorCatID string) (err error)
	ReorderCategories2(ctx *jxcontext.Context, vendorOrgCode, vendorParentCatID string, vendorCatIDList []string) (err error)

	// sku
	// CreateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
	// UpdateSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)
	// DeleteSku(db *dao.DaoDB, sku *model.Sku, userName string) (err error)

	// ReadSku(ctx *jxcontext.Context, vendorOrgCode, vendorSkuID string) (skuNameExt *model.SkuNameExt, err error)
	CreateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error)
	UpdateSku2(ctx *jxcontext.Context, sku *dao.StoreSkuSyncInfo) (err error)
	DeleteSku2(ctx *jxcontext.Context, vendorOrgCode string, sku *StoreSkuInfo) (err error)

	// RefreshAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool) (hint string, err error)

	GetSkus(ctx *jxcontext.Context, vendorOrgCode string, skuID int, vendorSkuID string) (skuNameList []*SkuNameInfo, err error)
}

type ISingleStoreHandler interface {
	IPurchasePlatformHandler
	ISingleStoreStoreSkuHandler
	// SyncStoreCategory(ctx *jxcontext.Context, parentTask tasksch.ITask, storeID int, isAsync bool) (hint string, err error)

	// RefreshStoresAllSkusID(ctx *jxcontext.Context, parentTask tasksch.ITask, isAsync bool, storeIDs []int) (hint string, err error)
}

type BasePurchasePlatform struct {
}

func (p *BasePurchasePlatform) GetStatusActionTimeout(order *model.GoodsOrder, statusType, status int) (params *StatusActionParams) {
	return params
}

func (c *BasePurchasePlatform) CanSwitch2SelfDeliver(order *model.GoodsOrder) (isCan bool, err error) {
	return true, nil
}

func init() {
	PurchasePlatformHandlers = make(map[int]IPurchasePlatformHandler)
	PurchaseOrderHandlers = make(map[int]IPurchasePlatformOrderHandler)
	DeliveryPlatformHandlers = make(map[int]*DeliveryPlatformHandlerInfo)
}

func InitOrderManager(curOrderManager IOrderManager) {
	CurOrderManager = curOrderManager
}

func InitStoreManager(curStoreManager IStoreManager) {
	CurStoreManager = curStoreManager
}

func RegisterPurchasePlatform(handler IPurchasePlatformHandler) {
	vendorID := handler.GetVendorID()
	if !(model.IsPurchaseVendorExist(vendorID)) {
		panic(fmt.Sprintf("purchase vendor:%d is illegal", vendorID))
	}
	if _, ok := PurchasePlatformHandlers[vendorID]; ok {
		panic(fmt.Sprintf("purchase vendor:%d, already exists", vendorID))
	}
	_, isSingleStore := handler.(ISingleStoreHandler)
	_, isMultiStore := handler.(IMultipleStoresHandler)
	if !isSingleStore && !isMultiStore {
		panic(fmt.Sprintf("platform:%d type is wrong!", vendorID))
	}
	PurchasePlatformHandlers[vendorID] = handler
}

func RegisterPurchaseOrderHandler(vendorID int, handler IPurchasePlatformOrderHandler) {
	PurchaseOrderHandlers[vendorID] = handler
}

func GetPurchasePlatformFromVendorID(vendorID int) IPurchasePlatformHandler {
	return PurchasePlatformHandlers[vendorID]
}

func GetPurchaseOrderHandlerFromVendorID(vendorID int) (handler IPurchasePlatformOrderHandler) {
	handler = PurchasePlatformHandlers[vendorID]
	if handler == nil {
		handler = PurchaseOrderHandlers[vendorID]
	}
	return handler
}

func GetPurchasePlatformVendorIDs() (vendorIDs []int) {
	for k := range PurchasePlatformHandlers {
		vendorIDs = append(vendorIDs, k)
	}
	return vendorIDs
}

func GetMultiStoreVendorIDs() (vendorIDs []int) {
	for k, v := range PurchasePlatformHandlers {
		if _, ok := v.(IMultipleStoresHandler); ok {
			vendorIDs = append(vendorIDs, k)
		}
	}
	return vendorIDs
}

func GetSingleStoreVendorIDs() (vendorIDs []int) {
	for k, v := range PurchasePlatformHandlers {
		if _, ok := v.(ISingleStoreHandler); ok {
			vendorIDs = append(vendorIDs, k)
		}
	}
	return vendorIDs
}

func IsMultiStore(vendorID int) bool {
	if _, ok := GetPurchasePlatformFromVendorID(vendorID).(IMultipleStoresHandler); ok {
		return true
	}
	return false
}

func GetRidderPositionGetter(vendorID int) (handler IRidderPositionGetter) {
	if handlerInfo := GetDeliveryPlatformFromVendorID(vendorID); handlerInfo != nil {
		if handler, _ = handlerInfo.Handler.(IRidderPositionGetter); handler != nil {
			return handler
		}
	}
	handler, _ = GetPurchasePlatformFromVendorID(vendorID).(IRidderPositionGetter)
	return handler
}

func GetWaybillTipUpdater(vendorID int) (handler IAddWaybillTip) {
	if handlerInfo := GetDeliveryPlatformFromVendorID(vendorID); handlerInfo != nil {
		if handler, _ = handlerInfo.Handler.(IAddWaybillTip); handler != nil {
			return handler
		}
	}
	handler, _ = GetPurchasePlatformFromVendorID(vendorID).(IAddWaybillTip)
	return handler
}
