package cn.freemud.fuyou.service.processor;

import cn.freemud.enums.PayChannelEnum;
import cn.freemud.fuyou.controller.request.DiscountRequest;
import cn.freemud.fuyou.controller.request.PayQueryRequest;
import cn.freemud.fuyou.controller.request.PaymentRequest;
import cn.freemud.fuyou.feign.request.Product;
import cn.freemud.fuyou.service.PaymentService;
import com.alibaba.fastjson.JSON;
import com.freemud.application.sdk.api.couponcenter.offline.domain.ProductRedeemVO;
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.OrderSettlementType;
import com.freemud.application.sdk.api.ordercenter.request.OrderSettlementReq;
import com.freemud.application.sdk.api.ordercenter.request.create.OrderItemCreateReq;
import com.freemud.application.sdk.api.ordercenter.request.create.OrderSettlementCreateReq;
import com.freemud.application.sdk.api.ordercenter.response.BaseResponse;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderInfoReqs;
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.CodePayRequest;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
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.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import static cn.freemud.management.util.ResponseCodeEnum.SUCCESS;


/***
 * 结算方式抽象
 */
@Setter
@Getter
@Slf4j
public abstract class AbstractProcessor implements EventProcessor {


    protected final OrderSdkService orderSdkService;
    protected final PaymentService paymentService;


    protected AbstractProcessor(OrderSdkService orderSdkService, PaymentService paymentService) {
        this.orderSdkService = orderSdkService;
        this.paymentService = paymentService;
    }

    /**
     * 转换支付 参数
     * @param orderItemList
     * @return
     */
    protected List<CodePayRequest.PayProduct> convertPayProduct(List<OrderItemCreateReq> orderItemList) {
        List<CodePayRequest.PayProduct> products = new ArrayList<>();
        if (CollectionUtils.isEmpty(orderItemList)) {
            return products;
        }

        orderItemList.stream().forEach((OrderItemCreateReq obj) -> {
            CodePayRequest.PayProduct product =new CodePayRequest.PayProduct();
            product.setId(obj.getProductId());
            product.setName(obj.getProductName());
            product.setPrice(obj.getSalePrice());
            product.setQuantity(obj.getProductQuantity());
            products.add(product);
        });

        return products;
    }

    /**
     * 转换支付 参数
     * @param orderItemList
     * @return
     */
    protected List<Product> convertProductRedeemVO(List<OrderItemCreateReq> orderItemList) {
        List<Product> products = new ArrayList<>();
        if (CollectionUtils.isEmpty(orderItemList)) {
            return products;
        }

        orderItemList.stream().forEach((OrderItemCreateReq obj) -> {
            Product product =new Product();
            product.setId(obj.getProductId());
            product.setName(obj.getProductName());
            product.setPrice(obj.getSalePrice());
            product.setQuantity(obj.getProductQuantity());
            products.add(product);
        });

        return products;
    }


    /**
     * 获取订详情
     *
     * @param orderCOde 订单号
     * @return
     */
    protected OrderInfoReqs getOrder(String orderCOde) {
        QueryByCodeResponse orderInfo = orderSdkService.getOrderInfo(orderCOde, 0, LogThreadLocal.getTrackingNo());
        if (ObjectUtils.notEqual(ResponseConstant.SUCCESS_RESPONSE_CODE, orderInfo.getCode())) {
            throw new RuntimeException("订单号不存在");
        }
        return orderInfo.getResult();
    }

    /**
     * 根据三方订单号查询
     * @param thirdOrderCode
     * @return
     */
    protected 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();
    }

    @Override
    public BaseResponse process(DiscountRequest request) {
        // 三方订单号兑换 订单信息
        OrderInfoReqs orderInfoReqs = getOrderByThirdOrderCode(request.getThirdOrderCode(),request.getOrderClient());
        request.setOrderInfoReqs(orderInfoReqs);
        log.info("process.DiscountRequest:{}", JSON.toJSONString(request));
        BaseResponse response = doProcess(request);
        if (ObjectUtils.notEqual(SUCCESS.code, response.getCode())) {
            return response;
        }
        log.info("AbstractProcessor.process,orderCode:{},responst:{}", orderInfoReqs.getOrderCode(), JSON.toJSONString(response));
        OrderSettlementReq orderSettlement = getOrderSettlement(request);
        // 2.创建结算信息
        // todo  分布式事物处理
        BaseResponse settlement = orderSdkService.createSettlement(orderSettlement, LogThreadLocal.getTrackingNo());
        if (ObjectUtils.notEqual(ResponseConstant.SUCCESS_RESPONSE_CODE, settlement.getCode())) {
            postProcessors(request);
            throw new RuntimeException("创建结算信息失败");
        }
        final PayChannelEnum payChannelEnum = PayChannelEnum.payChannelEnumMap.get(request.getPayChannel());
        if(Objects.nonNull(payChannelEnum)){
            // 订单支付完成
            final PayQueryRequest paymentRequest = mapper.map(request, PayQueryRequest.class);
            return paySuccess(paymentRequest);

        }
        return response;
    }

    /**
     * 支付完成
     * @param request
     * @return
     */
    BaseResponse paySuccess(PayQueryRequest request){
        return paymentService.paymentQuery(request);
    }

    /**
     * 业务处理
     *
     * @param request
     * @return
     */
    abstract BaseResponse doProcess(DiscountRequest request);


    /**
     * @param note            注释
     * @param type            结算类型
     * @param online          是否线上
     * @param orderInfoReqs
     * @param discountRequest
     * @return
     */
    OrderSettlementReq buildOrderSettlement(String note, OrderSettlementType type, Boolean online, OrderInfoReqs orderInfoReqs, DiscountRequest discountRequest) {
        OrderSettlementReq settlementReq = new OrderSettlementReq();
        settlementReq.setOrderClient(99);
        settlementReq.setOrderCode(orderInfoReqs.getOrderCode());
        settlementReq.setPartnerId(orderInfoReqs.getPartnerId());
        settlementReq.setThirdOrderCode(orderInfoReqs.getThirdOrderCode());
        //积分消费
        OrderSettlementCreateReq orderSettlementCreateReq = new OrderSettlementCreateReq();
        orderSettlementCreateReq.setNote(note);
        orderSettlementCreateReq.setSettlementType(type.getIndex());
        //orderSettlementCreateReq.setExternalObjectId(accountRequest.getAccountId());
        orderSettlementCreateReq.setNumber(1);
        //商家优惠
        orderSettlementCreateReq.setShopDiscountAmount(0L);
        //结算金额
        orderSettlementCreateReq.setSettlementAmount(discountRequest.getPayAmount());
        //是否线上 false:不是 true:是
        orderSettlementCreateReq.setIsOnline(online);
        orderSettlementCreateReq.setExtInfo(JSON.toJSONString(discountRequest));
        settlementReq.setOrderSettlementDetailList(Lists.newArrayList(orderSettlementCreateReq));
        return settlementReq;
    }

    /**
     * 获取构造结算数据
     *
     * @return
     */
    abstract OrderSettlementReq getOrderSettlement(DiscountRequest request);

    /**
     *  后置处理器 结算失败后会走,由各个业务处理，数据一致性
     * @return
     */
    protected boolean postProcessors(DiscountRequest request){return true;}





}
