package ebai

import (
	"fmt"
	"strings"

	"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/model"
	"git.rosy.net.cn/jx-callback/business/partner"
	"git.rosy.net.cn/jx-callback/globals"
	"git.rosy.net.cn/jx-callback/globals/api"
)

var (
	AfsVendorStatus2Status4PartRefundMap = map[int]int{
		ebaiapi.OrderPartRefundApply:                model.AfsOrderStatusWait4Approve,
		ebaiapi.OrderPartRefundSuccess:              model.AfsOrderStatusFinished,
		ebaiapi.OrderPartRefundUserApplyArbitration: model.OrderStatusUnknown, // 是否是中间状态
		ebaiapi.OrderPartRefundFailed:               model.AfsOrderStatusFailed,
		ebaiapi.OrderPartRefundMerchantRefused:      model.AfsOrderStatusFailed, // 是否是中间状态
	}
	AfsVendorStatus2Status4UserCancel = map[int]int{
		ebaiapi.OrderUserCancelApply:           model.AfsOrderStatusWait4Approve,
		ebaiapi.OrderUserCancelCSIntervene:     model.OrderStatusUnknown,
		ebaiapi.OrderUserCancelCSRefused:       model.AfsOrderStatusFailed,
		ebaiapi.OrderUserCancelCSAgreed:        model.AfsOrderStatusFinished,
		ebaiapi.OrderUserCancelMerchantRefused: model.AfsOrderStatusFailed,
		ebaiapi.OrderUserCancelMerchantAgreed:  model.AfsOrderStatusFinished,
		ebaiapi.OrderUserCancelInvalid:         model.AfsOrderStatusFailed,
	}
)

func (c *PurchaseHandler) isAfsMsg(msg *ebaiapi.CallbackMsg) bool {
	if msg.Cmd == ebaiapi.CmdOrderPartRefund {
		msgType := int(utils.MustInterface2Int64(msg.Body["type"]))
		return msgType == ebaiapi.OrderPartRefuncTypeCustomer || msgType == ebaiapi.OrderPartRefuncTypeCS
	} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
		cancelType := int(utils.MustInterface2Int64(msg.Body["cancel_type"]))
		return cancelType == ebaiapi.OrderUserCancelTypeAfterSale
	}
	return false
}

func (c *PurchaseHandler) OnAfsOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) {
	jxutils.CallMsgHandlerAsync(func() {
		retVal = c.onAfsOrderMsg(msg)
	}, jxutils.ComposeUniversalOrderID(GetOrderIDFromMsg(msg), model.VendorIDEBAI))
	return retVal
}

func (c *PurchaseHandler) onAfsOrderMsg(msg *ebaiapi.CallbackMsg) (retVal *ebaiapi.CallbackResponse) {
	if orderStatus := c.callbackAfsMsg2Status(msg); orderStatus != nil {
		var err error
		if orderStatus.Status == model.AfsOrderStatusWait4Approve || orderStatus.Status == model.AfsOrderStatusNew {
			var afsOrder *model.AfsOrder
			if msg.Cmd == ebaiapi.CmdOrderPartRefund {
				partRefundData := msg.Data.(*ebaiapi.CBPartRefundInfo)
				afsOrder = &model.AfsOrder{
					VendorID:         model.VendorIDEBAI,
					AfsOrderID:       orderStatus.VendorOrderID,
					VendorOrderID:    orderStatus.RefVendorOrderID,
					VendorStoreID:    "",
					StoreID:          0,
					AfsCreatedAt:     utils.Timestamp2Time(msg.Timestamp),
					VendorAppealType: "",
					AppealType:       model.AfsAppealTypeRefund,
					VendorReasonType: partRefundData.ReasonType,
					ReasonType:       c.convertAfsReasonType(partRefundData.ReasonType),
					ReasonDesc:       utils.LimitUTF8StringLen(buildFullReason(partRefundData.Reason, partRefundData.AdditionReason), 1024),
					ReasonImgList:    utils.LimitUTF8StringLen(strings.Join(partRefundData.Photos, ","), 1024),
					RefundType:       model.AfsTypePartRefund,

					VendorOrgCode: msg.Source,
					// FreightUserMoney:      afsInfo.OrderFreightMoney,
					// AfsFreightMoney:       afsInfo.AfsFreight,
					// BoxMoney:              afsInfo.PackagingMoney,
					// TongchengFreightMoney: afsInfo.TongchengFreightMoney,
					// SkuBoxMoney:           afsInfo.MealBoxMoney,
				}
				for _, sku := range partRefundData.RefundProducts {
					orderSku := &model.OrderSkuFinancial{
						// VendorID:      model.VendorIDEBAI,
						// AfsOrderID:    afsOrder.AfsOrderID,
						// VendorOrderID: afsOrder.VendorOrderID,
						// VendorStoreID: afsOrder.VendorStoreID,
						// StoreID:       afsOrder.StoreID,
						// IsAfsOrder:        1,

						Count: sku.Number,
						// ConfirmTime:          afsOrder.AfsCreateAt,
						VendorSkuID:       sku.SkuID,
						SkuID:             int(utils.Str2Int64WithDefault(sku.CustomSkuID, 0)),
						Name:              sku.Name,
						UserMoney:         sku.TotalRefund,
						PmSkuSubsidyMoney: sku.ShopEleRefund,
					}
					afsOrder.SkuUserMoney += orderSku.UserMoney
					afsOrder.PmSubsidyMoney += orderSku.PmSubsidyMoney
					afsOrder.Skus = append(afsOrder.Skus, orderSku)
				}
			} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
				if afsOrder = c.createAfsOrder(msg); afsOrder != nil {
					// if orderFinancial, err2 := partner.CurOrderManager.LoadOrderFinancial(orderStatus.RefVendorOrderID, model.VendorIDEBAI); err2 == nil {
					// afsOrder = c.OrderFinancialDetail2Refund(orderFinancial, msg)
					cancelData := msg.Data.(*ebaiapi.CBUserCancelInfo)
					afsOrder.AfsOrderID = orderStatus.VendorOrderID
					afsOrder.RefundType = model.AfsTypeFullRefund
					afsOrder.AppealType = model.AfsAppealTypeRefund
					afsOrder.VendorReasonType = ""
					afsOrder.ReasonType = model.AfsReasonNotOthers
					afsOrder.ReasonDesc = utils.LimitUTF8StringLen(buildFullReason(cancelData.CancelReason, cancelData.AdditionReason), 1024)
					afsOrder.ReasonImgList = utils.LimitUTF8StringLen(strings.Join(cancelData.Pictures, ","), 1024)
				}
			}
			if afsOrder != nil {
				err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
			}
		} else {
			if afsOrder2, err := partner.CurOrderManager.LoadAfsOrder(orderStatus.VendorOrderID, orderStatus.VendorID); afsOrder2 == nil && err == nil {
				partRefundData := msg.Data.(*ebaiapi.CBPartRefundInfo)
				afsOrder := &model.AfsOrder{
					VendorID:         model.VendorIDEBAI,
					AfsOrderID:       orderStatus.VendorOrderID,
					VendorOrderID:    orderStatus.RefVendorOrderID,
					VendorStoreID:    "",
					StoreID:          0,
					AfsCreatedAt:     utils.Timestamp2Time(msg.Timestamp),
					VendorAppealType: "",
					AppealType:       model.AfsAppealTypeRefund,
					VendorReasonType: partRefundData.ReasonType,
					ReasonType:       c.convertAfsReasonType(partRefundData.ReasonType),
					ReasonDesc:       utils.LimitUTF8StringLen(buildFullReason(partRefundData.Reason, partRefundData.AdditionReason), 1024),
					ReasonImgList:    utils.LimitUTF8StringLen(strings.Join(partRefundData.Photos, ","), 1024),
					RefundType:       model.AfsTypePartRefund,
					VendorOrgCode:    msg.Source,
				}
				for _, sku := range partRefundData.RefundProducts {
					orderSku := &model.OrderSkuFinancial{
						Count:             sku.Number,
						VendorSkuID:       sku.SkuID,
						SkuID:             int(utils.Str2Int64WithDefault(sku.CustomSkuID, 0)),
						Name:              sku.Name,
						UserMoney:         sku.TotalRefund,
						PmSkuSubsidyMoney: sku.ShopEleRefund,
					}
					afsOrder.SkuUserMoney += orderSku.UserMoney
					afsOrder.PmSubsidyMoney += orderSku.PmSubsidyMoney
					afsOrder.Skus = append(afsOrder.Skus, orderSku)
				}
				if afsOrder != nil {
					err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
				}
			} else {
				err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus)
			}
		}
		retVal = api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, nil)
	}
	return retVal
}

func (p *PurchaseHandler) createAfsOrder(msg *ebaiapi.CallbackMsg) (afsOrder *model.AfsOrder) {
	cancelData := msg.Data.(*ebaiapi.CBUserCancelInfo)
	afsOrder, err := partner.CurOrderManager.CreateAfsOrderFromOrder(utils.Int64ToStr(cancelData.OrderID), model.VendorIDEBAI)
	if err == nil {
		afsOrder.AfsOrderID = afsOrder.VendorOrderID
		afsOrder.AfsCreatedAt = utils.Timestamp2Time(msg.Timestamp)
	} else {
		afsOrder = nil
	}
	return afsOrder
}

func (c *PurchaseHandler) convertAfsReasonType(vendorReasonType string) int8 {
	return model.AfsReasonNotOthers
}

func (c *PurchaseHandler) GetAfsStatusFromVendorStatus4PartRefund(vendorStatus int) int {
	return AfsVendorStatus2Status4PartRefundMap[vendorStatus]
}

func (c *PurchaseHandler) GetAfsStatusFromVendorStatus4UserCancel(vendorStatus int) int {
	return AfsVendorStatus2Status4UserCancel[vendorStatus]
}

func (c *PurchaseHandler) callbackAfsMsg2Status(msg *ebaiapi.CallbackMsg) (orderStatus *model.OrderStatus) {
	if msg.Cmd == ebaiapi.CmdOrderPartRefund {
		partRefundData := msg.Data.(*ebaiapi.CBPartRefundInfo)
		orderStatus = &model.OrderStatus{
			VendorOrderID:    partRefundData.RefundID, // 是售后单ID，不是订单ID，订单ID在RefVendorOrderID中
			VendorID:         model.VendorIDEBAI,
			OrderType:        model.OrderTypeAfsOrder,
			RefVendorOrderID: utils.Int64ToStr(partRefundData.OrderID),
			RefVendorID:      model.VendorIDEBAI,
			VendorStatus:     utils.Int2Str(partRefundData.Status),
			Status:           c.GetAfsStatusFromVendorStatus4PartRefund(partRefundData.Status),
			StatusTime:       utils.Timestamp2Time(msg.Timestamp),
			Remark:           buildFullReason(partRefundData.Reason, partRefundData.AdditionReason),
		}
		if orderStatus.Status == model.AfsOrderStatusWait4Approve && partRefundData.Type != ebaiapi.OrderPartRefuncTypeCustomer {
			orderStatus.Status = model.AfsOrderStatusNew
		}
	} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
		cancelData := msg.Data.(*ebaiapi.CBUserCancelInfo)
		orderStatus = &model.OrderStatus{
			VendorOrderID:    utils.Int64ToStr(cancelData.OrderID), // 是售后单ID，不是订单ID，订单ID在RefVendorOrderID中
			VendorID:         model.VendorIDEBAI,
			OrderType:        model.OrderTypeAfsOrder,
			RefVendorOrderID: utils.Int64ToStr(cancelData.OrderID),
			RefVendorID:      model.VendorIDEBAI,
			VendorStatus:     utils.Int2Str(cancelData.Type),
			Status:           c.GetAfsStatusFromVendorStatus4UserCancel(cancelData.Type),
			StatusTime:       utils.Timestamp2Time(msg.Timestamp),
			Remark:           buildFullReason(cancelData.CancelReason, cancelData.AdditionReason),
		}
	}
	return orderStatus
}

// 审核售后单申请
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
	if globals.EnableEbaiStoreWrite {
		if approveType == partner.AfsApproveTypeRefused {
			err = api.EbaiAPI.OrderDisagreeRefund(order.VendorOrderID, reason)
		} else {
			err = api.EbaiAPI.OrderAgreeRefund(order.VendorOrderID)
		}
	}
	return err
}

// 确认收到退货
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
	err = fmt.Errorf("内部错误，饿百平台不支持确认收到退货操作")
	return err
}

// 发起全款退款
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
	return c.PartRefundOrder(ctx, order, order.Skus, reason)
}

// 发起部分退款
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
	if globals.EnableEbaiStoreWrite {
		if order.Status > model.OrderStatusEndBegin {
			return fmt.Errorf("饿百暂不支持售后退款！")
		}
		err = api.EbaiAPI.OrderPartRefund(order.VendorOrderID, orderSkus2AfsSkus(refundSkuList))
	}
	return err
}

func orderSkus2AfsSkus(refundSkuList []*model.OrderSku) (removeSkuList []*ebaiapi.RefundSku) {
	for _, v := range refundSkuList {
		refundSku := &ebaiapi.RefundSku{
			CustomeSkuID: utils.Int2Str(v.SkuID),
			Number:       utils.Int2Str(v.Count),
		}
		removeSkuList = append(removeSkuList, refundSku)
	}
	return removeSkuList
}

func (c *PurchaseHandler) GetOrderAfsInfo(ctx *jxcontext.Context, vendorOrderID, afsOrderID string) (orderAfsInfo *partner.OrderAfsInfo, err error) {
	orderAfsInfo = &partner.OrderAfsInfo{}
	if result, err := api.EbaiAPI.OrderPartRefundGet(vendorOrderID); err == nil {
		orderAfsInfo.VendorOrderID = vendorOrderID
		orderAfsInfo.AfsTotalShopMoney = utils.MustInterface2Int64(result["shop_fee"])
	}
	return orderAfsInfo, err
}
