package ebai

import (
	"errors"
	"fmt"
	"git.rosy.net.cn/jx-callback/business/model/dao"
	"strings"
	"time"

	"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, // 是否是中间状态
	}

	AfsVendorStatus2Status4ReverseRefundMap = map[int]int{
		//ebaiapi.OrderReversePushApplyInit:        model.AfsOrderStatusWait4Approve,        // 初始化售后
		ebaiapi.OrderReversePushApply:            model.AfsOrderStatusWait4Approve,        // 申请售后
		ebaiapi.OrderReversePushApplyRefuse:      model.AfsOrderStatusFailed,              // 售后失败
		ebaiapi.OrderReversePushApplyArbitration: model.AfsOrderStatusReceivedArbitration, // 仲裁
		ebaiapi.OrderReversePushApplyClose:       model.AfsOrderStatusFinished,            // 售后结束
		ebaiapi.OrderReversePushApplySuccess:     model.AfsOrderStatusFinished,            // 售后成功
		ebaiapi.OrderReversePushApplyFail:        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 {
	switch msg.Cmd {
	case ebaiapi.CmdOrderPartRefund:
		msgType := int(utils.MustInterface2Int64(msg.Body["type"]))
		return msgType == ebaiapi.OrderPartRefuncTypeCustomer || msgType == ebaiapi.OrderPartRefuncTypeCS || msgType == ebaiapi.OrderPartRefuncTypeMerchant
	case ebaiapi.CmdOrderUserCancel:
		// 1表示订单完成前用户全单取消申请流程， 2表示订单完成后用户全单退款申请流程
		cancelType := int(utils.MustInterface2Int64(msg.Body["cancel_type"]))
		return cancelType == ebaiapi.OrderUserCancelTypeAfterSale || cancelType == ebaiapi.OrderUserCancelTypeBeforeSale
	case ebaiapi.CmdOrderReversePush: // 订单逆向消息推送
		return true
	}

	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 {
				afsOrder = c.makeAfsOrderInfoPartRefund(msg, orderStatus)
			} else if msg.Cmd == ebaiapi.CmdOrderReversePush {
				afsOrder, err = c.makeAfsOrderInfoReverseRefund(msg, orderStatus)
				if err != nil {
					return api.EbaiAPI.Err2CallbackResponse(msg.Cmd, err, nil)
				}
			} else if msg.Cmd == ebaiapi.CmdOrderUserCancel {
				if afsOrder = c.createAfsOrder(msg); afsOrder != nil {
					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 {
			afsOrder2, _ := partner.CurOrderManager.LoadAfsOrder(orderStatus.VendorOrderID, orderStatus.VendorID)
			if afsOrder2 == nil && msg.Cmd == ebaiapi.CmdOrderPartRefund {
				afsOrder := c.makeAfsOrderInfoPartRefund(msg, orderStatus)
				if afsOrder != nil {
					err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
				}
			} else if afsOrder2 == nil && msg.Cmd == ebaiapi.CmdOrderReversePush {
				afsOrder, _ := c.makeAfsOrderInfoReverseRefund(msg, orderStatus)
				if afsOrder != nil {
					err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
				}
			} else if afsOrder2 == nil && msg.Cmd == ebaiapi.CmdOrderUserCancel {
				// 暂时未找到消息api
				afsOrder, _ := c.makeAfsOrderInfoMerchantAgreed(msg, orderStatus)
				if afsOrder != nil {
					err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
				}
			} else {
				err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus)
			}
		}

		// 只有有售后订单就更新此订单的结算信息
		var db = dao.GetDB()
		if (msg.Cmd == ebaiapi.CmdOrderUserCancel && orderStatus.Status == model.AfsOrderStatusFinished) || (msg.Cmd == ebaiapi.CmdOrderPartRefund && utils.Str2Int(orderStatus.VendorStatus) == ebaiapi.OrderPartRefundSuccess) || (msg.Cmd == ebaiapi.CmdOrderReversePush && utils.Str2Int(orderStatus.VendorStatus) == ebaiapi.OrderReversePushApplySuccess) {
			orderData, err2 := api.EbaiAPI.OrderPartRefundGet(orderStatus.RefVendorOrderID)
			if err2 == nil && utils.MustInterface2Int64(orderData["merchant_income"]) != model.NO {
				goodsOrder, _ := partner.CurOrderManager.LoadOrder(orderStatus.RefVendorOrderID, model.VendorIDEBAI)
				goodsOrder.TotalShopMoney = utils.MustInterface2Int64(orderData["merchant_income"])
				// 门店结算小于等于50为扣点
				var earningPrice int64 = 0
				for _, v := range goodsOrder.Skus {
					if goodsOrder.EarningType == model.EarningTypeQuote {
						earningPrice += v.ShopPrice * int64(v.Count)
					} else {
						earningPrice += v.SalePrice * int64(v.Count)
					}
				}
				goodsOrder.EarningPrice = earningPrice

				afsSkuList, _ := dao.GetStoreAfsOrderSkuList2(db, []string{goodsOrder.VendorOrderID})
				for _, v := range goodsOrder.Skus {
					for _, v2 := range afsSkuList {
						if v.VendorSkuID == v2.VendorSkuID && v2.IsAfsOrder == model.YES {
							switch goodsOrder.EarningType {
							case model.EarningTypeQuote: // 报价
								goodsOrder.EarningPrice = goodsOrder.EarningPrice - (v.ShopPrice * int64(v2.Count))
							case model.EarningTypePoints:
								afsOrder, _ := partner.CurOrderManager.LoadAfsOrder(v2.AfsOrderID, v2.VendorID)
								goodsOrder.EarningPrice = goodsOrder.EarningPrice - afsOrder.AfsTotalShopMoney
							}
						}
					}
				}

				dao.UpdateEntity(dao.GetDB(), goodsOrder, "TotalShopMoney", "EarningPrice")
			}
		}

		afs, err := partner.CurOrderManager.LoadAfsOrder(orderStatus.VendorOrderID, model.VendorIDEBAI)
		if msg.Cmd == ebaiapi.CmdOrderPartRefund {
			switch utils.Str2Int(orderStatus.VendorStatus) {
			case ebaiapi.OrderUserCancelMerchantAgreed, ebaiapi.OrderUserCancelCSAgreed:
				afs.Status = orderStatus.Status
				afs.VendorStatus = orderStatus.VendorStatus
				afs.Flag = model.YES
			case ebaiapi.OrderUserCancelCSRefused, ebaiapi.OrderUserCancelMerchantRefused, ebaiapi.OrderUserCancelInvalid:
				afs.Status = orderStatus.Status
				afs.VendorStatus = orderStatus.VendorStatus
				afs.Flag = 3
			}
		} else if msg.Cmd == ebaiapi.CmdOrderReversePush {
			switch utils.Str2Int(orderStatus.VendorStatus) {
			case ebaiapi.OrderReversePushApplySuccess:
				afs.Status = orderStatus.Status
				afs.VendorStatus = orderStatus.VendorStatus
				afs.Flag = model.YES
			case ebaiapi.OrderReversePushApplyRefuse, ebaiapi.OrderReversePushApplyFail:
				afs.Status = orderStatus.Status
				afs.VendorStatus = orderStatus.VendorStatus
				afs.Flag = 3
			}
		}
		if afs != nil {
			dao.UpdateEntity(db, afs, "Status", "VendorStatus", "Flag")
		}

		//if orderStatus.Status == model.AfsOrderStatusFinished {
		//	goodsOrder, _ := partner.CurOrderManager.LoadOrder(orderStatus.RefVendorOrderID, model.VendorIDEBAI)
		//	afsSkuList, _ := dao.GetOrderRefundSkuList(db, []string{goodsOrder.VendorOrderID})
		//	var afsSku int = 0
		//	for _, v := range afsSkuList {
		//		afsSku += v.Count
		//	}
		//	if afsSku == goodsOrder.GoodsCount && goodsOrder.GoodsCount != 0 {
		//		goodsOrder.Status = model.OrderStatusCanceled
		//		goodsOrder.VendorStatus = orderStatus.VendorStatus
		//		dao.UpdateEntity(db, goodsOrder, "Status", "VendorStatus")
		//	}
		//}

		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) GetAfsStatusFromVendorStatus4ReverseRefund(vendorStatus int) int {
	return AfsVendorStatus2Status4ReverseRefundMap[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.CmdOrderReversePush {
		partRefundData := msg.Data.(*ebaiapi.CBOrderReversePush)
		orderStatus = &model.OrderStatus{
			VendorOrderID:    utils.Int64ToStr(partRefundData.RefundOrderId), // 是售后单ID，不是订单ID，订单ID在RefVendorOrderID中
			VendorID:         model.VendorIDEBAI,
			OrderType:        model.OrderTypeAfsOrder,
			RefVendorOrderID: partRefundData.OrderId,
			RefVendorID:      model.VendorIDEBAI,
			VendorStatus:     utils.Int2Str(partRefundData.CurReverseEvent.RefundStatus),
			Status:           c.GetAfsStatusFromVendorStatus4ReverseRefund(partRefundData.CurReverseEvent.RefundStatus),
			StatusTime:       utils.Timestamp2Time(msg.Timestamp),
			Remark:           partRefundData.CurReverseEvent.RefundReasonDesc,
		}
	} 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, review map[string]interface{}) (err error) {
	if globals.EnableEbaiStoreWrite {
		param := &ebaiapi.RefundOrderExamine{
			ReverseOrderId: order.AfsOrderID,
			OrderId:        order.VendorOrderID,
			IdempotentId:   utils.Int64ToStr(time.Now().UnixNano()),
			ActionType:     ebaiapi.RefundTypeRefuse,
			ReasonCode:     "7001",
			ReasonRemarks:  reason,
		}
		refundProductList := make([]*ebaiapi.RefundProductList, 0, 0)
		date, _, _ := api.EbaiAPI.GetReverseOrder(order.VendorOrderID)
		for _, v := range date {
			v2 := v.(map[string]interface{})
			refundProduct := &ebaiapi.RefundProductList{
				SubBizOrderId: v2["sub_biz_order_id"].(string),
				PlatformSkuId: utils.Int64ToStr(utils.Interface2Int64WithDefault(v2["platform_sku_id"], 0)),
			}
			if order.AfsOrderID == order.VendorOrderID {
				param.ReverseOrderId = utils.Int64ToStr(utils.MustInterface2Int64(v2["refund_order_id"]))
			}
			switch utils.MustInterface2Int64(v2["fund_calculate_type"]) {
			case 0:
				refundProduct.Number = utils.Int64ToStr(utils.MustInterface2Int64(v2["refund_quantity"]))
			case 1:
				refundProduct.RefundAmount = utils.Int64ToStr(utils.MustInterface2Int64(v2["refund_user_amount"]))
			}
			refundProductList = append(refundProductList, refundProduct)
		}

		if approveType == partner.AfsApproveTypeRefused {
			if reason == "" {
				return fmt.Errorf("拒绝退单时请填写原因")
			}
			param.RefundProductList = refundProductList
			err = api.EbaiAPI.OrderDisagreeReturnGoods(param)
		} else if approveType == partner.AfsApproveTypeRefusedToRefundMoney {
			return errors.New("此平台暂时不支持,退货转退款")
		} else {
			param.ActionType = ebaiapi.RefundTypeAgree
			param.ReasonRemarks = reason
			err = api.EbaiAPI.OrderAgreeReturnGoods(param)
		}
	}
	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 order.Status < model.OrderStatusEndBegin {
		return fmt.Errorf("订单处于未结束状态,请稍后重试")
	}
	eabiApi := api.EbaiAPI

	date, removerAll, err := api.EbaiAPI.GetReverseOrder(order.VendorOrderID)
	if err != nil {
		return err
	}
	//售后部分多次退款
	if removerAll {
		param := &ebaiapi.RefundOrderExamine{
			ReverseOrderId: "",
			OrderId:        order.VendorOrderID,
			IdempotentId:   utils.Int64ToStr(time.Now().UnixNano()),
			ActionType:     ebaiapi.RefundTypeAgree,
			ReasonCode:     "",
			ReasonRemarks:  reason,
		}
		refundProductList := make([]*ebaiapi.RefundProductList, 0, 0)
		if date != nil && len(date) != model.NO {
			for _, v := range date {
				v2 := v.(map[string]interface{})
				refundProduct := &ebaiapi.RefundProductList{
					SubBizOrderId: v2["sub_biz_order_id"].(string),
					PlatformSkuId: utils.Int64ToStr(utils.Interface2Int64WithDefault(v2["platform_sku_id"], 0)),
				}
				param.ReverseOrderId = utils.Int64ToStr(utils.MustInterface2Int64(v2["refund_order_id"]))
				switch utils.MustInterface2Int64(v2["fund_calculate_type"]) {
				case 0:
					refundProduct.Number = utils.Int64ToStr(utils.MustInterface2Int64(v2["refund_quantity"]))
				case 1:
					refundProduct.RefundAmount = utils.Int64ToStr(utils.MustInterface2Int64(v2["refund_user_amount"]))
				}
				refundProductList = append(refundProductList, refundProduct)
			}
			param.RefundProductList = refundProductList
		}
		err = eabiApi.OrderAgreePartRefund(param)
	} else {
		orderDetail, err := eabiApi.OrderGet2(order.VendorOrderID)
		if err != nil {
			return err
		}
		skuList2 := make([]*ebaiapi.RefundProductListParam, 0, 0)
		for _, r := range refundSkuList {
			for _, v := range orderDetail.Products[0] {
				if utils.Int2Str(jxutils.GetSkuIDFromOrderSku(r)) == v.CustomSkuID || r.VendorSkuID == v.BaiduProductID {
					skuList2 = append(skuList2, &ebaiapi.RefundProductListParam{
						SubBizOrderId:     v.SubBizOrderID,
						PlatformSkuId:     v.BaiduProductID,
						Number:            utils.Int2Str(r.Count),
						RefundAmount:      "",
						FundCalculateType: "0",
					})
				}
			}
		}

		// 部分退款
		err = eabiApi.OrderReverseApply(&ebaiapi.OrderReverseApplyParam{
			OrderId:           order.VendorOrderID,
			IdempotentId:      utils.Int64ToStr(time.Now().Unix()),
			RefundType:        ebaiapi.MerchantOrderReverseApplyPartCancel,
			ReasonCode:        "7015",
			ReasonRemarks:     reason,
			NeedIvrUser:       1,
			RefundProductList: skuList2,
		})

		//if reason == "" {
		//	return fmt.Errorf("拒绝退单时,请填写拒单原因")
		//}
		//if err := api.EbaiAPI.OrderPartRefund(order.VendorOrderID, orderSkus2AfsSkus(refundSkuList)); err != nil {
		//	return err
		//}
	}
	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{}
	//result, _, err := api.EbaiAPI.GetReverseOrder(vendorOrderID)
	//if err == nil {
	//	orderAfsInfo.VendorOrderID = vendorOrderID
	//	var afsTotalShopMoney int64 = 0
	//	for _, v := range result {
	//		v2 := v.(map[string]interface{})
	//		afsTotalShopMoney += utils.MustInterface2Int64(v2["refund_user_amount"])
	//	}
	//	orderAfsInfo.AfsTotalShopMoney = afsTotalShopMoney
	//}
	//return orderAfsInfo, err

	orderAfsInfo = &partner.OrderAfsInfo{}
	if result, err := api.EbaiAPI.OrderPartRefundGet(vendorOrderID); err == nil {
		orderAfsInfo.VendorOrderID = vendorOrderID
		orderAfsInfo.AfsTotalShopMoney = utils.MustInterface2Int64(result["merchant_income"])
	}
	return orderAfsInfo, err
}
