package cn.freemud.management.service.impl;

import cn.freemud.base.entity.BaseResponse;
import cn.freemud.management.entities.dto.request.order.OrderManagerRequest;
import cn.freemud.management.entities.dto.response.order.OrderManagerResponse;
import cn.freemud.management.entities.dto.response.pay.PayRefundResponse;
import cn.freemud.management.enums.OperateType;
import cn.freemud.management.enums.ResponseResult;
import cn.freemud.management.service.OrderBaseService;
import cn.freemud.management.service.OrderManagerService;
import cn.freemud.management.service.handle.OrderCouponHandle;
import cn.freemud.management.service.handle.PaymentHandle;
import cn.freemud.management.service.handle.SaasOrderHandle;
import cn.freemud.management.service.handle.StockHandle;
import cn.freemud.management.util.ResponseUtil;
import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.log.ApiLog;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.entities.v1.OrderBeanV1;
import com.freemud.application.sdk.api.ordercenter.request.AfterSalesRefundFailReq;
import com.freemud.application.sdk.api.ordercenter.service.OrderSdkService;
import com.freemud.sdk.api.assortment.order.enums.PayRefundStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.UUID;

import static cn.freemud.management.enums.OperateType.ORDER_AGREE_REFUND;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @version V1.0
 * @Title: rrr
 * @Package cn.freemud.management.service.impl
 * @Description: saas订单履单操作
 * @author: shuhu.hou
 * @date: 2020/3/26 16:01
 * @Copyright: 2020 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Service
public class SaleCouponOrderMangerServiceImpl implements OrderManagerService {

    @Autowired
    private OrderCouponHandle orderCouponHandle;

    @Autowired
    private SaasOrderHandle saasOrderHandle;
    @Autowired
    private OrderBaseService orderBaseService;

    @Autowired
    private PaymentHandle paymentHandle;
    @Autowired
    private StockHandle stockHandle;

    @Autowired
    private OrderSdkService orderSdkService;


    /**
     * 同意退款
     *
     * @param request
     * @param orderBean
     * @return
     */
    @Override
    public BaseResponse<OrderManagerResponse> orderAgreeRefund(OrderManagerRequest request, OrderBeanV1 orderBean) {

        // 支付退款 包括线上小程序付款的订单，订单宝其他支付方式收款（汇来米，收钱吧，现金，其他）老板通发起退款
        PayRefundResponse refundResponse = this.payRefundCommon(request, orderBean);
        // 退款异常
        if (refundResponse.getPayRefundStatus().getCode().compareTo(PayRefundStatus.COMPATIBILITY_STATUS.getCode()) == 0) {
            return ResponseUtil.error(refundResponse.getResult());
        }
        //退款失败终止下面的退款流程
        if (refundResponse.getPayRefundStatus().getCode().compareTo(PayRefundStatus.FAIL.getCode()) == 0) {
            return ResponseUtil.error(ResponseResult.REFUND_FAIL.getCode(), refundResponse.getMessage());
        }

        // 先退款再作废券，因为退款经常出现余额不足而失败。券作废失败不影响后面的流程
        try {
            BaseResponse response = orderCouponHandle.discardOrderCoupon(request.getPartnerId(), orderBean);
            if (!isSuccess(response)) {
                ApiLog.warnMessage("卖券订单已退款，优惠券作废失败 oid:{} resp:{}", orderBean.getOid(), JSONObject.toJSONString(response));
            }
        } catch (Throwable e) {
            ApiLog.warnMessage("卖券订单已退款，优惠券作废异常 oid:{} ex:{}", orderBean.getOid(), e.getMessage());
        }


        //订单同意退款
        saasOrderHandle.refundAgree(request, refundResponse, orderBean);
        // 推送pos、微信消息中心
        orderBaseService.sendMessage(orderBean, ORDER_AGREE_REFUND, request.getReason());

        // 退款冲正发送消息队列（部分退款不进行冲正）
        if (!refundResponse.getPartRefund()) {
            // todo 可以考虑基于订单回调异步实现
            stockHandle.revert(request, orderBean);
        }

        if (refundResponse.getPayRefundStatus().getCode().compareTo(PayRefundStatus.RUNNING.getCode()) == 0) {
            return ResponseUtil.error(ResponseResult.REFUND_FAIL.getCode(), refundResponse.getMessage());
        }
        return ResponseUtil.success();
    }

    /**
     * 拒绝退款
     *
     * @param request
     * @param orderBean
     * @return
     */
    @Override
    public BaseResponse<OrderManagerResponse> orderRejectRefund(OrderManagerRequest request, OrderBeanV1 orderBean) {
        //拒绝退款
        BaseResponse response = saasOrderHandle.refundReject(request, orderBean);
        if (!isSuccess(response)) {
            return response;
        }
        // 推送pos、微信消息中心
        orderBaseService.sendMessage(orderBean, OperateType.ORDER_REJECT_REFUND, request.getReason());

        // 拒绝后解冻券
        try {
            orderCouponHandle.unfreezeOrderCoupon(request.getPartnerId(), orderBean);
        } catch (Exception e) {
            ApiLog.warnMessage("refundReject 解冻券异常.error orderCode={}, ex:{}", request.getOrderId(), e.getMessage());
        }
        return ResponseUtil.success();
    }




    /**
     * 拒单退款、同意退款、取消订单退款
     * 小程序点餐订单退款，无单收银退款，订单宝扫码付、其他支付方式收款（汇来米，收钱吧，现金，其他）等有支付流水等退款
     */
    private PayRefundResponse payRefundCommon(OrderManagerRequest request, OrderBeanV1 orderBean) {
        if (orderBean.getAmount() == 0) {
            // 0元订单
            PayRefundResponse refundResponse = new PayRefundResponse();
            refundResponse.setRefundId(UUID.randomUUID().toString().replaceAll("-", ""));
            refundResponse.setPayRefundStatus(PayRefundStatus.SUCCESS);
            refundResponse.setMessage(PayRefundStatus.SUCCESS.getDesc());
            return refundResponse;
        }
        PayRefundResponse refundResponse = paymentHandle.getCommonPayRefundResponse(request, orderBean);
        // 同意退款退款失败记录到订单售后单
        if (orderBean.getAfterSalesOrderResp() != null && Objects.equals(PayRefundStatus.FAIL.getCode(), refundResponse.getPayRefundStatus().getCode())) {
            AfterSalesRefundFailReq refundFailReq = this.getAfterSalesRefundFailReq(orderBean,
                    request.getOperator(),
                    request.getOperationClient(),
                    refundResponse.getMessage());
            orderSdkService.refundFail(refundFailReq, LogThreadLocal.getTrackingNo());
        }
        return refundResponse;
    }

    private AfterSalesRefundFailReq getAfterSalesRefundFailReq(OrderBeanV1 orderBean, String operator, Integer operationClient, String refundFailReason) {
        AfterSalesRefundFailReq refundFailReq = new AfterSalesRefundFailReq();
        refundFailReq.setOrderCode(orderBean.getOid());
        refundFailReq.setPartnerId(orderBean.getCompanyId());
        refundFailReq.setRefundFailReason(refundFailReason);
        refundFailReq.setAfterSalesCode(orderBean.getAfterSalesOrderResp().getAfterSalesCode());
        refundFailReq.setOperationClient(operationClient);
        refundFailReq.setOperator(operator);
        return refundFailReq;
    }


    private boolean isSuccess(BaseResponse response) {
        return Objects.equals("100", response.getCode());
    }
}
