package cn.freemud.fuyou.service;


import cn.freemud.base.constant.Version;
import cn.freemud.enums.OrderStatus;
import cn.freemud.enums.PayStatus;
import cn.freemud.fuyou.controller.request.*;
import cn.freemud.fuyou.controller.response.FuYouCreateOrderResponse;
import cn.freemud.fuyou.feign.CouponFeignClient;
import cn.freemud.fuyou.feign.ScoreFeignClient;
import cn.freemud.fuyou.feign.request.CouponAvailableReqVo;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.fuyou.feign.request.ReturnScoreRequest;
import cn.freemud.fuyou.feign.response.*;
import cn.freemud.fuyou.service.processor.CashEventProcessor;
import cn.freemud.utils.LogUtil;
import cn.freemud.utils.ResponseUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.freemud.application.sdk.api.couponcenter.offline.domain.ProductRedeemVO;
import com.freemud.application.sdk.api.couponcenter.offline.domain.TransactionVO;
import com.freemud.application.sdk.api.couponcenter.offline.request.CouponRequest;
import com.freemud.application.sdk.api.couponcenter.offline.service.OfflineCouponSdkService;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.constant.ResponseConstant;
import com.freemud.application.sdk.api.ordercenter.enums.NewOrderStatus;
import com.freemud.application.sdk.api.ordercenter.enums.OrderSettlementType;
import com.freemud.application.sdk.api.ordercenter.enums.ResponseResultEnum;
import com.freemud.application.sdk.api.ordercenter.request.OrderCancelReq;
import com.freemud.application.sdk.api.ordercenter.request.OrderChangeStateReq;
import com.freemud.application.sdk.api.ordercenter.request.create.OrderItemCreateReq;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderInfoReqs;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderItemResp;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderSettlementResp;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.QueryByCodeResponse;
import com.freemud.application.sdk.api.ordercenter.service.OrderSdkService;
import com.freemud.application.sdk.api.paymentcenter.client.request.OrderRefundNewRequest;
import com.freemud.application.sdk.api.paymentcenter.client.response.RefundNewResponse;
import com.freemud.application.sdk.api.paymentcenter.client.service.PaymentNewService;
import com.freemud.card.sdk.vo.coupon.CouponStateVo;
import com.freemud.sdk.api.assortment.order.enums.ResponseResult;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.stereotype.Service;

import java.util.*;

import static cn.freemud.enums.ResponseResult.*;


@Service
@Slf4j
public class FuYouOrderService {

    private final OrderSdkService orderSdkService;
    private final MapperFacade mapperFacade;
    private final CouponFeignClient couponFeignClient;
    private final PaymentNewService paymentNewService;
    private final OfflineCouponSdkService offlineCouponSdkService;
    private final ScoreFeignClient scoreFeignClient;

    public FuYouOrderService(OrderSdkService orderSdkService, MapperFacade mapperFacade,
                             CouponFeignClient couponFeignClient,
                             PaymentNewService paymentNewService, OfflineCouponSdkService offlineCouponSdkService,
                             ScoreFeignClient scoreFeignClient) {
        this.orderSdkService = orderSdkService;
        this.mapperFacade = mapperFacade;
        this.couponFeignClient = couponFeignClient;
        this.paymentNewService = paymentNewService;
        this.offlineCouponSdkService = offlineCouponSdkService;
        this.scoreFeignClient = scoreFeignClient;
    }


    private List<Product> convertProduct(List<OrderItemCreateReq> orderItemList) {
        List<Product> productList = Lists.newArrayList();
        orderItemList.stream().forEach((OrderItemCreateReq obj) -> {
            Product product = new Product();
            product.setQuantity(obj.getProductQuantity());
            product.setAmount(obj.getProductPrice().intValue());
            product.setProductId(obj.getProductId());
            productList.add(product);
        });
        return productList;
    }

    private List<com.freemud.card.sdk.vo.coupon.Product> convertCouponProduct(List<OrderItemCreateReq> orderItemList) {
        List<com.freemud.card.sdk.vo.coupon.Product> productList = Lists.newArrayList();
        orderItemList.stream().forEach((OrderItemCreateReq obj) -> {
            com.freemud.card.sdk.vo.coupon.Product product = new com.freemud.card.sdk.vo.coupon.Product();
            product.setQuantity(obj.getProductQuantity());
            product.setAmount(obj.getProductPrice().intValue());
            product.setProductId(obj.getProductId());
            productList.add(product);
        });
        return productList;
    }


    /**
     * 创建订单
     *
     * @param request
     * @return
     */
    public BaseResponse<FuYouCreateOrderResponse> createOrder(CreateOrderRequest request) {
        com.freemud.application.sdk.api.ordercenter.request.create.CreateOrderRequest baseCreateOrderRequest = mapperFacade.map(request, com.freemud.application.sdk.api.ordercenter.request.create.CreateOrderRequest.class);
        final com.freemud.application.sdk.api.ordercenter.response.BaseResponse<OrderInfoReqs> orderInfoReqsBaseResponse = orderSdkService.createOrder(baseCreateOrderRequest, LogThreadLocal.getTrackingNo());
        //下单
        if (ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(), orderInfoReqsBaseResponse.getCode())) {
            return ResponseUtil.error(orderInfoReqsBaseResponse.getCode(), orderInfoReqsBaseResponse.getMessage(), null);
        }
        FuYouCreateOrderResponse orderResponse = new FuYouCreateOrderResponse();
        orderResponse.setOrderCode(orderInfoReqsBaseResponse.getResult().getOrderCode());

        // 获取券码
        if (CollectionUtils.isNotEmpty(request.getCouponList())) {
            CouponAvailableReqVo availableReqVo = new CouponAvailableReqVo();
            availableReqVo.setCouponCodes(request.getCouponList());
            availableReqVo.setProductList(convertProduct(request.getOrderItemList()));
            availableReqVo.setTotalAmount(request.getSettlementAmount().intValue());
            availableReqVo.setMerchantId(request.getPartnerId());
            availableReqVo.setProviderId(request.getPartnerId());
            CouponAvailableRespDto couponsAvailable = couponFeignClient.getCouponsAvailable(availableReqVo);
            LogUtil.info("availableCoupon_couponAvailableService.getCouponsAvailable", JSON.toJSONString(availableReqVo), JSON.toJSONString(couponsAvailable));

            if (ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(), couponsAvailable.getResult())) {
                ResponseUtil.error(cn.freemud.enums.ResponseResult.COUPON_QUERY_ERROR);
            }
            if (Objects.equals(String.valueOf(couponsAvailable.getResult()), ResponseResult.SUCCESS.getCode())
                    && CollectionUtils.isNotEmpty(couponsAvailable.getCouponStateList())) {
                //couponStateList.addAll(couponsAvailable.getCouponStateList());
                couponsAvailable.getCouponStateList().stream().forEach((CouponStateVo obj) -> {

                    if (Objects.equals(obj.getState(), 0)) {
                        //可用
                        obj.setProductList(convertCouponProduct(request.getOrderItemList()));
                        orderResponse.getEffectiveCouponList().add(obj);
                    } else if (Objects.equals(obj.getState(), 1)) {
                        //不可用
                        orderResponse.getInvalidCouponList().add(obj);
                    } else {
                        //部分可用
                        if (Objects.equals(obj.getLimitType(), "0")) {
                            orderResponse.getEffectiveCouponList().add(obj);
                        } else {
                            //无效的优惠券
                            orderResponse.getInvalidCouponList().add(obj);
                        }
                    }


                });
            }
        }
        return ResponseUtil.success(orderResponse);
    }

    /**
     * 退款
     * TODO  需要分布式事物处理
     *
     * @param req
     * @return
     */
    public BaseResponse refund(RefundRequest req) {
        // 1.退款
        QueryByCodeResponse orderInfo = orderSdkService.getOrderInfo(req.getOrderClient(), null,req.getThirdOrderCode(),null, LogThreadLocal.getTrackingNo());
        if (ObjectUtils.notEqual(ResponseConstant.SUCCESS_RESPONSE_CODE, orderInfo.getCode())) {
           return ResponseUtil.error(orderInfo.getCode(),orderInfo.getMessage());
        }
        final OrderInfoReqs order = orderInfo.getResult();
        if (ObjectUtils.notEqual(order.getPayState(), PayStatus.HAVE_PAID.getCode())) {
            log.info("订单状态不对:{}", JSON.toJSONString(order));
            return ResponseUtil.error(cn.freemud.enums.ResponseResult.PAY_BACKEND_CONFIG_ERROR);
        }
        final OrderSettlementResp orderSettlementResp = getOrderSettlementResp(order);

        final BaseResponse baseResponse = doRefund(orderSettlementResp, order);
        if (ObjectUtils.notEqual(SUCCESS.getCode(), baseResponse.getCode())) {
            return baseResponse;
        }
        //3 .退优惠券
       return rectification(order, "富有商家退款");

    }

    /**
     * 获取支付方式
     *
     * @param order
     * @return
     */
    private OrderSettlementResp getOrderSettlementResp(OrderInfoReqs order) {
        //支付结算方式
        OrderSettlementResp payorderSeetlment = order.getOrderSettlementDetailList()
                .stream()
                .filter(obj -> {
                            if (OrderSettlementType.WEIXIN.getIndex() == obj.getSettlementType().intValue() ||
                                    OrderSettlementType.ALIPAY.getIndex() == obj.getSettlementType().intValue() ||
                                    OrderSettlementType.SVC.getIndex() == obj.getSettlementType().intValue() ||
                                    OrderSettlementType.CASH.getIndex() == obj.getSettlementType().intValue()) {
                                return true;
                            }
                            return false;
                        }

                ).findFirst().orElse(null);
        return payorderSeetlment;
    }

    private OrderInfoReqs getOrderByThirdOrderCode(String thirdOrderCode,String orderClient) {
        QueryByCodeResponse orderInfo = orderSdkService.getOrderInfo(orderClient,null,thirdOrderCode, null, LogThreadLocal.getTrackingNo());
        if (ObjectUtils.notEqual(ResponseConstant.SUCCESS_RESPONSE_CODE, orderInfo.getCode())) {
            throw new RuntimeException(orderInfo.getMessage());
        }
        return orderInfo.getResult();
    }

    /***
     * 支付完成
     * @param request
     * @return
     */
    public BaseResponse complete(CompleteRequest request) {
        OrderInfoReqs orderInfoReqs = getOrderByThirdOrderCode(request.getThirdOrderCode(), request.getOrderClient());
        BaseResponse response = new BaseResponse();
       if(ObjectUtils.notEqual(PayStatus.HAVE_PAID.getCode(),orderInfoReqs.getPayState())){
           return ResponseUtil.error(ORDER_NO_PAU);
       }
        OrderChangeStateReq req = new OrderChangeStateReq();
        req.setOrderState(OrderStatus.COMPLETE.getCode());
        req.setOrderCode(orderInfoReqs.getOrderCode());
        com.freemud.application.sdk.api.ordercenter.response.BaseResponse baseResponse = orderSdkService.updateOrderState(req, LogThreadLocal.getTrackingNo());
        response.setCode(baseResponse.getCode());
        response.setMessage(baseResponse.getMessage());
        return response;
    }

    ;

    /***
     * 目前支持 优惠券，积分
     *
     * 冲正
     * @return
     */
    public BaseResponse rectification(OrderInfoReqs order, String reqRemark) {
        if (Objects.equals(order.getOrderState(), NewOrderStatus.COMPLETE.getIndex()) ||
                Objects.equals(order.getOrderState(), NewOrderStatus.CLOSED.getIndex())
                ) {
            log.info("rectification 订单状态已完成，或者已经关闭，不支持冲正");
            return ResponseUtil.error(ResponseResult.ORDER_QUERYORDER_ERROR.getCode(),"订单号不存在");
        }
        // 2.更改订单
        OrderCancelReq orderCancelReq = new OrderCancelReq();
        orderCancelReq.setPartnerId(order.getPartnerId());
        orderCancelReq.setOrderCode(order.getOrderCode());
        orderCancelReq.setReqRemark(reqRemark);
        orderCancelReq.setAfterSalesType(3);
        orderCancelReq.setOrderClient(2);
        orderCancelReq.setCreateEvent(4);
        com.freemud.application.sdk.api.ordercenter.response.BaseResponse cancelOrderResponse = orderSdkService.cancelOrder(orderCancelReq, LogThreadLocal.getTrackingNo());
        if (ObjectUtils.notEqual(SUCCESS, cancelOrderResponse.getCode())) {
            log.error("orderSdkService.cancelOrder.error,request:{},response:{}", JSON.toJSONString(orderCancelReq),
                    JSON.toJSONString(cancelOrderResponse));
            return ResponseUtil.error(cancelOrderResponse.getCode(),cancelOrderResponse.getMessage());
        }

        order.getOrderSettlementDetailList().forEach((OrderSettlementResp obj) -> {
            if (OrderSettlementType.COUPON.getIndex() == obj.getSettlementType().intValue()) {
                DiscountRequest discountRequest = JSONObject.parseObject(obj.getExtInfo(), DiscountRequest.class);
                CouponRequest couponCodeVerificationDto = new CouponRequest();
                couponCodeVerificationDto.setVer(Integer.valueOf(Version.VERSION_1));
                couponCodeVerificationDto.setReqtype(3);
                couponCodeVerificationDto.setPartnerId(Integer.parseInt(order.getPartnerId()));
                //自取：pickup，外送：delivery，麦咖啡微信小程序：mocoffee_wx，麦咖啡支付宝小程序：mocoffee_zfb
                couponCodeVerificationDto.setChannel("pickup");
                couponCodeVerificationDto.setStation_id(order.getPosCode());
                couponCodeVerificationDto.setOperator_id("-1");
                couponCodeVerificationDto.setStore_id(order.getStoreId());
                //核销不需要核销通知
                //couponCodeVerificationDto.setAppFlag("kgd.N");
                // 订单号 替换成唯一序号
                couponCodeVerificationDto.setTrans_id(order.getOrderCode());
                couponCodeVerificationDto.setBusiness_date(cn.freemud.base.util.DateUtil.convert2Str(new Date(), cn.freemud.base.util.DateUtil.FORMAT_yyyyMMdd));
                List<TransactionVO> transactions = new ArrayList<>();
                TransactionVO couponCodeVerificationTransDto = new TransactionVO();
                couponCodeVerificationTransDto.setCode(discountRequest.getCoupon());
                couponCodeVerificationTransDto.setTotalAmount(discountRequest.getPayAmount());
                List<ProductRedeemVO> productRedeemVOS = convertOrderItemCreateReq(order.getOrderItemList());
                couponCodeVerificationTransDto.setProducts(productRedeemVOS);
                transactions.add(couponCodeVerificationTransDto);
                couponCodeVerificationDto.setTransactions(transactions);
                com.freemud.application.sdk.api.base.BaseResponse baseResponse = offlineCouponSdkService.couponReverse(couponCodeVerificationDto, LogThreadLocal.getTrackingNo());
                if (ObjectUtils.notEqual(SUCCESS, baseResponse.getCode())) {
                    log.error("offlineCouponSdkService.couponReverse.error,request:{},response:{}", JSON.toJSONString(couponCodeVerificationDto),
                            JSON.toJSONString(baseResponse));
                }
            }
            if (OrderSettlementType.POINTS.getIndex() == obj.getSettlementType().intValue()) {
                ReturnScoreRequest returnScoreRequest = new ReturnScoreRequest();
                returnScoreRequest.setMemberId(order.getUserId());
                returnScoreRequest.setOrderId(order.getOrderCode());
                returnScoreRequest.setPartnerId(order.getPartnerId());
                returnScoreRequest.setOperationTypes(Lists.newArrayList(2));
                BaseResponse<UpdateScoreResponse> returnScore = scoreFeignClient.returnScore(returnScoreRequest);
                if (ObjectUtils.notEqual(SUCCESS.getCode(), returnScore.getCode())) {
                    log.error("scoreFeignClient.returnScore.error,request:{},response:{}", JSON.toJSONString(returnScoreRequest),
                            JSON.toJSONString(returnScore));
                }
            }
        });

        return ResponseUtil.success();
    }

    private List<ProductRedeemVO> convertOrderItemCreateReq(List<OrderItemResp> orderItemList) {
        List<ProductRedeemVO> products = new ArrayList<>();
        if (CollectionUtils.isEmpty(orderItemList)) {
            return products;
        }
        for (int i = 0; i < orderItemList.size(); i++) {
            //商品券核销核销参数
            ProductRedeemVO couponCodeVerificationProductDto = new ProductRedeemVO();
            couponCodeVerificationProductDto.setPid(UUID.randomUUID().toString());
            couponCodeVerificationProductDto.setConsume_num(orderItemList.get(i).getProductQuantity());
            couponCodeVerificationProductDto.setSeq(i);
            // couponCodeVerificationProductDto.setMerchantProductId(orderItemList.get(i).getProductId());
            products.add(couponCodeVerificationProductDto);
        }
        return products;
    }

    private BaseResponse doRefund(OrderSettlementResp payorderSeetlment, OrderInfoReqs order) {
        BaseRequest payRequest = JSONObject.parseObject(payorderSeetlment.getExtInfo(), BaseRequest.class);

        switch (payorderSeetlment.getSettlementType()) {
            case 203:
            case 204:
            case 19:
                //微信,支付宝,svc
                OrderRefundNewRequest refundRequest = new  OrderRefundNewRequest();
                refundRequest.setPartnerId(order.getPartnerId());
                refundRequest.setVer(2);
                refundRequest.setStoreId(order.getStoreId());
                refundRequest.setStationId(order.getPosCode());
                refundRequest.setTransId(order.getOrderCode());
                refundRequest.setFmId(payRequest.getFmId());
                refundRequest.setRefundId(UUID.randomUUID().toString());
                refundRequest.setTotalAmount(Long.valueOf(payRequest.getPayAmount()));
                refundRequest.setRefundAmount(Long.valueOf(payRequest.getPayAmount()));
                final com.freemud.application.sdk.api.base.BaseResponse<RefundNewResponse> refundResponse = paymentNewService.newOrderRefund(refundRequest,LogThreadLocal.getTrackingNo());
                if (ObjectUtils.notEqual(refundResponse.getCode(), ResponseResultEnum.SUCCESS.getCode())) {
                    return ResponseUtil.error(refundResponse.getCode(), refundResponse.getMessage());
                }
                return ResponseUtil.success();
            case 202:
                //现金
                return ResponseUtil.success();
            default:
                throw new IllegalStateException("Unexpected value: " + payorderSeetlment.getSettlementType());

        }
    }


}
