package basesch

import (
	"fmt"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
	"git.rosy.net.cn/jx-callback/business/jxstore/cms"
	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
	"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"
)

var (
	ctx *jxcontext.Context
)
var (
	FixedBaseScheduler *BaseScheduler
)

type BaseScheduler struct {
	IsReallyCallPlatformAPI bool
}

func (c *BaseScheduler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
	globals.SugarLogger.Infof("AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt)
	if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusNew || order.Status == model.OrderStatusWaitAccepted {
		if c.IsReallyCallPlatformAPI {
			err = utils.CallFuncLogErrorWithInfo(func() error {
				return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).AcceptOrRefuseOrder(order, isAcceptIt, userName)
			}, "AcceptOrRefuseOrder orderID:%s, isAcceptIt:%t", order.VendorOrderID, isAcceptIt)
		}
	} else {
		return scheduler.ErrOrderStatusAlreadySatisfyCurOperation
		globals.SugarLogger.Debugf("AcceptOrRefuseOrder orderID:%s, status:%d is not suitable, isAcceptIt:%t", order.VendorOrderID, order.Status, isAcceptIt)
	}
	return err
}

func (c *BaseScheduler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
	globals.SugarLogger.Infof("PickupGoods orderID:%s,order :%v", order.VendorOrderID, utils.Format4Output(order, false))
	if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusAccepted {
		if c.IsReallyCallPlatformAPI {
			handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID)
			err = utils.CallFuncLogErrorWithInfo(func() (err error) {
				if err = handler.PickupGoods(order, isSelfDelivery, userName); err != nil {
					if status, err2 := handler.GetOrderStatus(order.VendorOrgCode, order.VendorOrderID); err2 == nil && status >= model.OrderStatusFinished {
						err = nil
					}
				}
				return err
			}, "PickupGoods orderID:%s", order.VendorOrderID)
		}
	} else {
		if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusAccepted {
			err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation
			globals.SugarLogger.Infof("PickupGoods orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status)
		} else {
			err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation
			globals.SugarLogger.Debugf("PickupGoods orderID:%s status:%d already ok", order.VendorOrderID, order.Status)
		}
	}
	return err
}

func (c *BaseScheduler) Swtich2SelfDeliver(order *model.GoodsOrder, userName string) (err error) {
	globals.SugarLogger.Infof("Swtich2SelfDeliver orderID:%s", order.VendorOrderID)
	if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status >= model.OrderStatusFinishedPickup && order.Status <= model.OrderStatusDelivering {
		if order.DeliveryFlag&model.OrderDeliveryFlagMaskPurcahseDisabled == 0 && c.IsReallyCallPlatformAPI {
			err = utils.CallFuncLogErrorWithInfo(func() error {
				return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).Swtich2SelfDeliver(order, userName)
			}, "Swtich2SelfDeliver orderID:%s", order.VendorOrderID)
		}
		if err == nil { // 因为有些平台转自送后，不会再发送订单在配送中消息过来，所以成功后就强制设置状态为配送中
			order.Status = model.OrderStatusDelivering
			order.DeliveryFlag |= model.OrderDeliveryFlagMaskPurcahseDisabled
			err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order)
		}
	} else {
		if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusFinishedPickup || order.VendorID == order.WaybillVendorID {
			err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation
			globals.SugarLogger.Infof("Swtich2SelfDeliver orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status)
		} else {
			err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation
			globals.SugarLogger.Debugf("Swtich2SelfDeliver orderID:%s status:%d already ok", order.VendorOrderID, order.Status)
		}
	}
	return err
}

func (c *BaseScheduler) Swtich2SelfDelivered(order *model.GoodsOrder, userName string) (err error) {
	globals.SugarLogger.Infof("Swtich2SelfDelivered orderID:%s", order.VendorOrderID)
	if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusDelivering {
		if c.IsReallyCallPlatformAPI {
			err = utils.CallFuncLogError(func() error {
				return partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).Swtich2SelfDelivered(order, userName)
			}, "Swtich2SelfDelivered orderID:%s", order.VendorOrderID)
		}
	} else {
		if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusDelivering {
			err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation
			globals.SugarLogger.Infof("Swtich2SelfDelivered orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status)
		} else {
			err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation
			globals.SugarLogger.Debugf("Swtich2SelfDelivered orderID:%s status:%d already ok", order.VendorOrderID, order.Status)
		}
	}
	return err
}

func (c *BaseScheduler) SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
	globals.SugarLogger.Infof("SelfDeliverDelivering orderID:%s", order.VendorOrderID)
	if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status == model.OrderStatusFinishedPickup {
		if c.IsReallyCallPlatformAPI {
			err = utils.CallFuncLogError(func() error {
				if err := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).SelfDeliverDelivering(order, userName); err != nil {
					bill, _ := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID)
					c.CancelWaybill(bill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive)
				}
				return err
			}, "SelfDeliverDelivering orderID:%s", order.VendorOrderID)
			if err == nil { // 因为有些平台设置配送中后，不会发送订单在配送中消息过来，所以成功后就强制设置状态为配送中
				order.Status = model.OrderStatusDelivering
				err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order)
			}
		}
	} else {
		if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusFinishedPickup {
			err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation
			globals.SugarLogger.Infof("SelfDeliverDelivering orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status)
		} else {
			err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation
			globals.SugarLogger.Debugf("SelfDeliverDelivering orderID:%s, status:%d already ok", order.VendorOrderID, order.Status)
		}
	}
	return err
}

func (c *BaseScheduler) SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
	globals.SugarLogger.Infof("SelfDeliverDelivered orderID:%s", order.VendorOrderID)
	if /*order.LockStatus == model.OrderStatusUnknown && */ order.Status >= model.OrderStatusFinishedPickup &&
		order.Status <= model.OrderStatusDelivering {
		if c.IsReallyCallPlatformAPI {
			err = utils.CallFuncLogError(func() error {
				if err = partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).SelfDeliverDelivered(order, userName); err != nil {
					bill, _ := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID)
					c.CancelWaybill(bill, partner.CancelWaybillReasonOther, partner.CancelWaybillReasonStrActive)
				}
				return err
			}, "SelfDeliverDelivered orderID:%s", order.VendorOrderID)
		}
	} else {
		if order.LockStatus != model.OrderStatusUnknown || order.Status < model.OrderStatusDelivering {
			err = scheduler.ErrOrderStatusIsNotSuitable4CurOperation
			globals.SugarLogger.Infof("SelfDeliverDelivered orderID:%s, status:%d is not suitable", order.VendorOrderID, order.Status)
		} else {
			err = scheduler.ErrOrderStatusAlreadySatisfyCurOperation
			globals.SugarLogger.Debugf("SelfDeliverDelivered orderID:%s, status:%d already ok", order.VendorOrderID, order.Status)
		}
	}
	return err
}

func (c *BaseScheduler) CreateWaybill(platformVendorID int, order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
	globals.SugarLogger.Infof("CreateWaybill to meituan orderID:%s, vendor:%s", order.VendorOrderID, jxutils.GetVendorName(platformVendorID))
	if !model.IsOrderSolid(order) { // 如果订单是不完整的
		globals.SugarLogger.Warnf("CreateWaybill orderID:%s, vendorID:%d is not solid!!!", order.VendorOrderID, platformVendorID)
		return nil, scheduler.ErrOrderIsNotSolid
	}
	// if order.DeliveryFlag&model.OrderDeliveryFlagMaskScheduleDisabled != 0 {
	// 	waybillList, err := partner.CurOrderManager.GetOrderWaybillInfo(jxcontext.AdminCtx, order.VendorOrderID, order.VendorID, true)
	// 	if err != nil {
	// 		return nil, err
	// 	}
	// 	if len(waybillList) > 0 {
	// 		return nil, fmt.Errorf("转商家自送的订单只允许有一个有效运单，当前已经有%s运单", jxutils.GetVendorName(waybillList[0].WaybillVendorID))
	// 	}
	// }

	storeDetail, _ := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, order.VendorOrgCode)
	// 获取门店品牌余额
	storeAcct, err := cms.GetStoreAcctBalance(ctx, jxutils.GetSaleStoreIDFromOrder(order)) // 获取门店余额
	// 如果门店没钱,查看品牌，查询门店品牌id
	result, err := partner.CurStoreAcctManager.GetBrandBalance(storeDetail.BrandID) // 品牌余额
	if err != nil {
		return nil, err
	}
	var balance int

	// 门店发单,如果是京西门店,直接使用京西余额,非京西门店使用门店余额,余额不足使用品牌余额!
	if order.CreateDeliveryType == model.YES {
		if storeDetail.BrandID == scheduler.JXC4B_SHOP || storeDetail.BrandID == scheduler.JXC4B_RAND_JXGY { // 京西品牌,扣门店
			balance = storeAcct.AccountBalance
		} else {
			if storeAcct.AccountBalance >= model.BrandBalanceLimit {
				balance = storeAcct.AccountBalance
			} else if storeAcct.AccountBalance < model.BrandBalanceLimit && result >= model.BrandBalanceLimit {
				balance = result
			} else {
				balance = 0
			}
		}
	} else {
		balance, _ = partner.CurStoreAcctManager.GetBrandBalance(storeDetail.BrandID)
	}

	handlerInfo := partner.GetDeliveryPlatformFromVendorID(platformVendorID)
	if handlerInfo != nil && handlerInfo.Use4CreateWaybill {
		//if model.DeliveryBrandMarkMap[platformVendorID]&storeDetail.BrandIsOpen != 0 && balance >= model.BrandBalanceLimit {
		if _, ok := model.DeliveryBrandMarkMap[platformVendorID]; ok && storeDetail.BrandIsOpen != 0 && balance >= model.BrandBalanceLimit {
			if c.IsReallyCallPlatformAPI {
				// 美团配送订单生成，配送费计算
				bill, err = handlerInfo.Handler.CreateWaybill(order, maxDeliveryFee)
				if err != nil {
					globals.SugarLogger.Infof("CreateWaybill failed orderID:%s vendorID:%d with error:%v", order.VendorOrderID, platformVendorID, err)
				} else {
					order.DeliveryFlag |= model.WaybillVendorID2Mask(platformVendorID)
					err = partner.CurOrderManager.UpdateOrderStatusAndDeliveryFlag(order)
				}
			}
		} else {
			err = fmt.Errorf("CreateWaybill failed brand is close orderID: %s, isOpen: %d or store/brand money is enought ", order.VendorOrderID, storeDetail.BrandIsOpen)
		}
	} else {
		err = scheduler.ErrDeliverProviderWrong
	}
	return bill, err
}

func (c *BaseScheduler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) {
	globals.SugarLogger.Infof("CancelWaybill bill:%v, cancelReasonID:%d cancelReason:%s", bill, cancelReasonID, cancelReason)
	// 部分快递平台在取消成功后有时会不发运单取消消息过来（比如达达，904200512000442），为避免二次取消报错，添加状态判断
	if c.IsReallyCallPlatformAPI && bill.OrderVendorID != bill.WaybillVendorID && bill.Status != model.WaybillStatusCanceled {
		if handlerInfo := partner.GetDeliveryPlatformFromVendorID(bill.WaybillVendorID); handlerInfo != nil {
			if err = utils.CallFuncLogErrorWithInfo(func() error {
				return handlerInfo.Handler.CancelWaybill(bill, cancelReasonID, cancelReason)
			}, "CancelWaybill bill:%v", bill); err == nil {
				bill.Status = model.WaybillStatusCanceled
				bill.DeliveryFlag |= model.WaybillDeliveryFlagMaskActiveCancel
				_, err = dao.UpdateEntity(nil, bill, "Status", "DeliveryFlag")
			}
			globals.SugarLogger.Debugf("CancelWaybill bill:%v canceled by myself", bill)
		}
	}
	return err
}
