package cn.freemud.service.impl;

import cn.freemud.adapter.OrderAdapter;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.log.LogTreadLocal;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.entities.dto.order.CreateOrderOperateDto;
import cn.freemud.entities.dto.order.CreatePrepayRequestDto;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.CreateOrderResponseVo;
import cn.freemud.entities.vo.CreateOrderVo;
import cn.freemud.entities.vo.CreatePrepayVo;
import cn.freemud.enums.PayStatus;
import cn.freemud.enums.ResponseResult;
import cn.freemud.enums.TradeState;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.service.AppOrderService;
import cn.freemud.utils.ResponseUtil;
import com.alibaba.fastjson.JSONObject;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.enums.AfterSalesType;
import com.freemud.application.sdk.api.paymentcenter.client.request.PaymentCloseUnifiedOrderRequest;
import com.freemud.application.sdk.api.paymentcenter.client.request.PaymentQueryRequest;
import com.freemud.application.sdk.api.paymentcenter.client.response.PaymentCloseUnifiedOrderResponse;
import com.freemud.application.sdk.api.paymentcenter.client.response.PaymentQueryResponse;
import com.freemud.application.sdk.api.paymentcenter.client.service.PaymentNewService;
import com.freemud.application.sdk.api.storecenter.response.StoreResponse;
import com.freemud.sdk.api.assortment.order.entities.OrderExtInfoDTO;
import com.freemud.sdk.api.assortment.order.request.order.CancelOrderRequest;
import com.freemud.sdk.api.assortment.order.request.order.OrderEditRequest;
import com.freemud.sdk.api.assortment.order.request.order.QueryRelatedOrderByCodeRequest;
import com.freemud.sdk.api.assortment.order.response.order.BaseOrderResponse;
import com.freemud.sdk.api.assortment.order.response.order.QueryOrdersResponse;
import com.freemud.sdk.api.assortment.order.response.order.QueryRelatedOrderByCodeResp;
import com.freemud.sdk.api.assortment.order.service.OrderCenterSdkService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class AppOrderServiceImpl implements AppOrderService {

    @Autowired
    private OrderServiceImpl orderservice;
    @Autowired
    private CheckOrder checkOrder;
    @Autowired
    private OrderAdapter orderAdapter;
    @Autowired
    private OrderCenterSdkService orderCenterSdkService;
    @Autowired
    private PaymentNewService paymentNewService;

    /**
     * 不支持会员卡
     */
    @Override
    public BaseResponse createOrderFlow(CreateOrderVo createOrderVo) {
        String trackingNo = LogThreadLocal.getTrackingNo();
        // 查询用户信息
        AssortmentCustomerInfoVo userLoginInfoDto = checkOrder.checkOrderByMember(createOrderVo, trackingNo);
        // 查询门店信息 营业时间、营业状态，服务器当前时间在营业时间内 点餐桌号
        StoreResponse.BizVO storeResponseDto = checkOrder.checkOrderByStore(createOrderVo, trackingNo);
        // 查询购物车（内部校验券点餐方式，券是否可用） 校验当前订单类型的下单参数
        ShoppingCartGoodsDto shoppingCartGoodsDto = checkOrder.getShoppingCartGoodsDto(createOrderVo);
        // 查询小程序自提外卖配置信息 校验当前订单类型的下单参数 校验外卖是否满足起送条件
        Integer pushOrderTime = checkOrder.checkOrderByOrderType(createOrderVo, userLoginInfoDto, storeResponseDto,shoppingCartGoodsDto.getTotalAmount(), trackingNo);
        //1.5.4版本，商品库存校验与扣库存
        //List<String> stockProductIds = checkOrder.getStockProductIdList(createOrderVo, shoppingCartGoodsDto);
        OrderExtInfoDTO extInfo = orderservice.getExtInfo(userLoginInfoDto, storeResponseDto, pushOrderTime, createOrderVo);
        //创建订单
        CreateOrderOperateDto createOrderOperateDto = orderservice.sdkCreateOrder(createOrderVo, storeResponseDto, shoppingCartGoodsDto, userLoginInfoDto);
        BaseResponse baseResponse = this.updateOrderExtInfo(createOrderOperateDto.getProductOrderBean(), extInfo, trackingNo);
        if(baseResponse != null) {
            return baseResponse;
        }
        //返回没创建预支付的结果
        CreateOrderResponseVo responseVo = orderAdapter.convent2CreateFatherSonOrderNoPayResponseVo(createOrderOperateDto.getProductOrderBean());
        return ResponseUtil.success(responseVo);
    }

    @Override
    public BaseResponse createPrepay(CreatePrepayVo createPrepayVo) {
        CreateOrderOperateDto createOrderOperateDto = this.getCreateOrderOperateDto(createPrepayVo.getOrderCode());
        QueryOrdersResponse.DataBean.OrderBean productOrderBean = createOrderOperateDto.getProductOrderBean();
        this.checkOrderBefore(createPrepayVo, productOrderBean);
        // 关闭历史预支付订单
        this.closeHistoryPrePay(productOrderBean);
        OrderExtInfoDTO extInfo = JSONObject.parseObject(productOrderBean.getExtInfo(), OrderExtInfoDTO.class);
        extInfo.setAppid(createPrepayVo.getPayAppId());
        extInfo.setOpenid(createPrepayVo.getOpenId());
        String faceCode = "";
        String cardCode = "";
        CreatePrepayRequestDto createPrepayRequestDto = orderAdapter.convertToCreatePrepayRequestDto(createPrepayVo.getPartnerId(), createPrepayVo.getPayAppId(), createPrepayVo.getOpenId(), faceCode,
                cardCode, createPrepayVo.getPayCode(), createOrderOperateDto.getFatherOrderBean(), createOrderOperateDto.getProductOrderBean(), createOrderOperateDto.getTotalAmount(),
                createOrderOperateDto.getCardAmount(), extInfo);
        return orderservice.createPrepayOrder(createPrepayRequestDto);
    }

    private void checkOrderBefore(CreatePrepayVo createPrepayVo, QueryOrdersResponse.DataBean.OrderBean orderBean) {
        if(!PayStatus.NOT_PAY.getCode().equals(orderBean.getPayStatus())){
            throw new ServiceException(ResponseResult.ORDER_HAS_PAID);
        }
        OrderExtInfoDTO extInfo = JSONObject.parseObject(orderBean.getExtInfo(), OrderExtInfoDTO.class);
        if(extInfo == null || StringUtils.isBlank(extInfo.getSessionId()) || !extInfo.getSessionId().equals(createPrepayVo.getSessionId())) {
            throw new ServiceException(ResponseResult.ORDER_OWNER_ERROR);
        }
    }

    /**
     * 更新订单扩展信息 
     */
    private BaseResponse updateOrderExtInfo(QueryOrdersResponse.DataBean.OrderBean orderBean, OrderExtInfoDTO orderExtInfo, String trackingNo) {
        OrderEditRequest orderEditRequest = new OrderEditRequest(orderBean.getOid(), JSONObject.toJSONString(orderExtInfo));
        orderEditRequest.setTrackingNo(trackingNo);
        BaseOrderResponse baseOrderResponse = orderCenterSdkService.orderEdit(orderEditRequest);
        if (!ObjectUtils.equals(ResponseCodeConstant.RESPONSE_SUCCESS, baseOrderResponse.getErrcode())) {
            CancelOrderRequest cancelOrderRequest = orderAdapter.convent2CancelOrderRequest(orderBean.getOid(), orderBean.getCompanyId(),
                    AfterSalesType.SYSTEM_CANCEL, "编辑订单支付信息失败", trackingNo, null);
            orderCenterSdkService.orderCancel(cancelOrderRequest);
            return ResponseUtil.error(baseOrderResponse.getErrcode().toString(), baseOrderResponse.getErrmsg());
        }
        return null;
    }

    private CreateOrderOperateDto getCreateOrderOperateDto(String orderId){
        QueryRelatedOrderByCodeRequest baseQueryOrderRequest = new QueryRelatedOrderByCodeRequest();
        baseQueryOrderRequest.setOrderCode(orderId);
        baseQueryOrderRequest.setTrackingNo(LogTreadLocal.getTrackingNo());
        QueryRelatedOrderByCodeResp queryOrderByIdResponse = orderCenterSdkService.queryRelatedOrderByCode(baseQueryOrderRequest);
        if(queryOrderByIdResponse == null || CollectionUtils.isEmpty(queryOrderByIdResponse.getOrderBeanList())) {
            throw new ServiceException(ResponseResult.ORDER_QUERYORDER_ERROR);
        }
        List<QueryOrdersResponse.DataBean.OrderBean> orderBeanList = queryOrderByIdResponse.getOrderBeanList();
        long totalAmount = 0;
        QueryOrdersResponse.DataBean.OrderBean fatherBeanListOne = new QueryOrdersResponse.DataBean.OrderBean();
        QueryOrdersResponse.DataBean.OrderBean productBeanListOne = new QueryOrdersResponse.DataBean.OrderBean();
        if(1 == orderBeanList.size()) {
            fatherBeanListOne = orderBeanList.get(0);
            productBeanListOne = orderBeanList.get(0);
            totalAmount = orderBeanList.get(0).getAmount();
        } else {
            fatherBeanListOne = orderBeanList.stream().filter(orderBeanTemp -> orderBeanTemp.getIsParent()).findFirst().orElse(fatherBeanListOne);
            productBeanListOne = orderBeanList.stream().filter(orderBeanTemp -> 1 == orderBeanTemp.getBizType()).findFirst().orElse(productBeanListOne);
            totalAmount = orderBeanList.stream().mapToLong(QueryOrdersResponse.DataBean.OrderBean::getAmount).count();
        }

        CreateOrderOperateDto createOrderOperateDto = new CreateOrderOperateDto();
        createOrderOperateDto.setTotalAmount(totalAmount);
        createOrderOperateDto.setCardAmount(0);
        createOrderOperateDto.setFatherOrderBean(fatherBeanListOne);
        createOrderOperateDto.setProductOrderBean(productBeanListOne);
        return createOrderOperateDto;
    }

        private void closeHistoryPrePay(QueryOrdersResponse.DataBean.OrderBean orderBean) {
            OrderExtInfoDTO extInfo = JSONObject.parseObject(orderBean.getExtInfo(), OrderExtInfoDTO.class);
            //判断当前订单是否存在预支付订单
            if(extInfo != null && StringUtils.isNotEmpty(extInfo.getFmId())){
                //订单状态未支付且存在预支付订单：
                // 1.查询预支付订单支付状态
                PaymentQueryRequest paymentQueryRequest = new PaymentQueryRequest();
                paymentQueryRequest.setPartnerId(orderBean.getCompanyId());
                paymentQueryRequest.setStoreId(orderBean.getShopId());
                paymentQueryRequest.setFmId(extInfo.getFmId());
                paymentQueryRequest.setVer("2");
                com.freemud.application.sdk.api.base.BaseResponse<PaymentQueryResponse> queryResponseBaseResponse = paymentNewService.query(paymentQueryRequest,LogThreadLocal.getTrackingNo());
                //判断预支付订单状态
                if(ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(), queryResponseBaseResponse.getCode())){
                    throw new ServiceException(ResponseResult.ORDER_PAY_GETPRE_MESSAGE_ERROR);
                }
                //判断当前预支付订单是否已经支付成功
                if(ObjectUtils.equals(TradeState.SUCCESS.getCode(), queryResponseBaseResponse.getData().getTradeState())){
                    throw new ServiceException(ResponseResult.ORDER_HAS_PAID);
                }
                // 3.取消前一个预支付订单  调用支付取消预支付订单,如果预支付订单已经取消了再调用取消预支付订单接口会报错的
                if(ObjectUtils.equals(TradeState.NOTPAY.getCode(), queryResponseBaseResponse.getData().getTradeState())) {
                    PaymentCloseUnifiedOrderRequest closeUnifiedOrderRequest = new PaymentCloseUnifiedOrderRequest();
                    closeUnifiedOrderRequest.setFmId(extInfo.getFmId());
                    closeUnifiedOrderRequest.setVer("2");
                    closeUnifiedOrderRequest.setPartnerId(orderBean.getCompanyId());
                    closeUnifiedOrderRequest.setStoreId(orderBean.getShopId());
                    com.freemud.application.sdk.api.base.BaseResponse<PaymentCloseUnifiedOrderResponse> cancelNewUnifiedOrder = paymentNewService.cancelNewUnifiedOrder(closeUnifiedOrderRequest,LogThreadLocal.getTrackingNo());
                    if(ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(),cancelNewUnifiedOrder.getCode())){
                        throw new ServiceException(ResponseResult.ORDER_PRE_PAYMENT_CLOSE_FAILED);
                    }
                }
            }
        }
}
