package cn.freemud.service.impl;

import cn.freemud.adapter.LightApplicationConvertToAssortmentSdkAdapter;
import cn.freemud.adapter.OrderAdapter;
import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.log.LogTreadLocal;
import cn.freemud.entities.dto.ConfirmOrderDto;
import cn.freemud.entities.dto.QueryOrdersResponseDto;
import cn.freemud.entities.vo.AppCreateOrderVo;
import cn.freemud.base.log.LogTreadLocal;
import cn.freemud.base.util.DateUtil;
import cn.freemud.constant.RedisKeyConstant;
import cn.freemud.entities.dto.*;import cn.freemud.entities.dto.shoppingCart.NewShoppingCartClearDto;
import cn.freemud.entities.vo.AppCreateOrderVo;
import cn.freemud.entities.vo.CreateOrderVo;
import cn.freemud.entities.vo.CreatePrepayVo;
import cn.freemud.entities.vo.PaysuccessNoticeMessage;
import cn.freemud.entities.vo.encircle.CreateReserveOrderVo;
import cn.freemud.enums.*;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.*;
import cn.freemud.utils.LogUtil;
import cn.freemud.utils.RedisUtil;
import cn.freemud.utils.ResponseUtil;
import com.alibaba.fastjson.JSONObject;
import com.freemud.api.assortment.datamanager.entity.db.AssortmentCloudPrinter;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.enums.IappIdType;
import com.freemud.api.assortment.datamanager.manager.customer.AssortmentCustomerInfoManager;
import com.freemud.application.sdk.api.log.ErrorLog;
import com.freemud.sdk.api.assortment.order.enums.OrderSourceType;
import com.freemud.sdk.api.assortment.order.request.order.ConfirmOrderRequest;
import com.freemud.sdk.api.assortment.order.util.LockUtils;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @version V1.6.0
 * @Title: OrderAdapterServiceImpl
 * @Description: 订单业务适配
 * @author: qin.zhou
 * @date: 2019/9/818:22
 * @Copyright: ${DATE.YARE} www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Slf4j
@Service
public class OrderAdapterServiceImpl implements OrderAdapterService {

    private final String PAY_SUCCESS_KEY = "pay_success_key:";

    private static Gson gson = new Gson();

    @Value("${mccafe.partner.id}")
    private String mcCafePartnerId;

    @Autowired
    private EncircleOrderService encircleOrderService;
    @Autowired
    private OrderServiceImpl orderService;
    @Autowired
    private MCCafeOrderService mcCafeOrderService;
    @Autowired
    private AssortmentCustomerInfoManager assortmentCustomerInfoManager;
    @Autowired
    private MallOrderService mallOrderService;
    @Autowired
    private AppOrderService appOrderService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private OrderAdapter orderAdapter;
    @Autowired
    private OrderCommonService orderCommonService;
    @Autowired
    private SellCouponOrderServiceImpl sellCouponOrderService;

    @Override
    public BaseResponse createOrderNew(CreateOrderVo createOrderVo) {
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createOrderVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        // 扩展字段中存储 sessionKey
        createOrderVo.setSessionKey(assortmentCustomerInfoVo.getSessionKey());
        if(IappIdType.WC_XCX.getCode().equals(assortmentCustomerInfoVo.getIappId())){  //i围餐
            BaseResponse baseResponse = null;
            CreateReserveOrderVo createReserveOrderVo = new CreateReserveOrderVo();
            createReserveOrderVo.setCarVer(createOrderVo.getCarVer());
            createReserveOrderVo.setRepastNumber(createOrderVo.getPeopleNumber());
            createReserveOrderVo.setSessionId(createOrderVo.getSessionId());
            createReserveOrderVo.setOrderUpdateVer(createOrderVo.getOrderUpdateVer());
            createReserveOrderVo.setCouponCode(createOrderVo.getCouponCode());
            createReserveOrderVo.setUseCustomerScore(createOrderVo.getUseCustomerScore());
            createReserveOrderVo.setCardCode(createOrderVo.getCardCode());
            if(createOrderVo.getOperation() == null) throw new ServiceException(ResponseResult.ORDER_CREATE_OPERATION_ERROR);
            switch (createOrderVo.getOperation()){
                case 2:// 开台
                    baseResponse = encircleOrderService.createReserveOrder(createOrderVo);
                    break;
                case 3:// 下单
                    baseResponse = encircleOrderService.updateReserveOrder(createReserveOrderVo);
                    break;
                case 4:// 创建预支付订单
                    baseResponse = encircleOrderService.createPrepaymentOrder(createReserveOrderVo);
                    break;
                default:
                    throw new ServiceException(ResponseResult.ORDER_CREATE_OPERATION_ERROR);
            }
            return baseResponse;
        }

        /**
         * 商城订单
         */
        if(OrderChannelType.SAASMALL.getCode().equals(createOrderVo.getChannelType())) {
            return mallOrderService.createOrder(createOrderVo);
        }

        /**
         * APP下单
         */
        if (UserLoginChannelEnum.APP.getCode().equals(assortmentCustomerInfoVo.getChannel())) {
            return appOrderService.createOrderFlow(createOrderVo);
        }

        //原标准点餐程序逻辑处理
        BaseResponse baseResponse = this.checkStandardParamInfo(createOrderVo);
        if(ObjectUtils.notEqual(baseResponse.getCode(),ResponseResult.SUCCESS.getCode())){
            return baseResponse;
        }
        return orderService.createOrderNew(createOrderVo);
    }


    @Override
    public BaseResponse createMCCafeOrder(CreateOrderVo createOrderVo) {
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createOrderVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        if(!mcCafePartnerId.equals(assortmentCustomerInfoVo.getPartnerId())) {
            return ResponseUtil.error(ResponseResult.LOGIN_STORE_ERROR);
        }
        // 扩展字段中存储 sessionKey
        createOrderVo.setSessionKey(assortmentCustomerInfoVo.getSessionKey());

        //原标准点餐程序逻辑处理
        BaseResponse baseResponse = this.checkStandardParamInfo(createOrderVo);
        if(ObjectUtils.notEqual(baseResponse.getCode(),ResponseResult.SUCCESS.getCode())){
            return baseResponse;
        }
        return mcCafeOrderService.createMCCafeOrder(createOrderVo);
    }

    @Override
    public BaseResponse createPrepay(CreatePrepayVo createPrepayVo) {
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createPrepayVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        if (UserLoginChannelEnum.APP.getCode().equals(assortmentCustomerInfoVo.getChannel())) {
            return appOrderService.createPrepay(createPrepayVo);
        }
        throw new UnsupportedOperationException("暂不支持渠道："+assortmentCustomerInfoVo.getChannel());
    }

    @Override
    public String paySuccessCallback(PaysuccessNoticeMessage message) {
        if (StringUtils.isEmpty(message.getTrans_id())){
            return orderAdapter.newSendPayFaileMessage();
        }
        //添加分布式锁，如果没有取得锁直接返回失败；整个方法执行完毕后会删掉该锁
        String paySuccessKey = PAY_SUCCESS_KEY + message.getTrans_id();
        if(!LockUtils.lockAfter(redisCache.getRedisTemplate(), paySuccessKey)){
            return orderAdapter.newSendPayFaileMessage();
        }
        try {
            ConfirmOrderDto confirmOrderDto = orderAdapter.convent2ConfirmOrderDto(message);
            // 通过交易号从缓存中拿订单号，如果有数据则实际订单号为其value值
            String orderId = redisCache.getValue(RedisUtil.getPaymentTransIdOrderKey(confirmOrderDto.getOrderId()));
            if (StringUtils.isNotBlank(orderId)) {
                log.info("从缓存中获取的订单数据,trackingNo:{},transId:{},orderId:{}", LogTreadLocal.getTrackingNo(), confirmOrderDto.getOrderId(), orderId);
                confirmOrderDto.setOrderId(orderId);
            }
            Map<String, QueryOrdersResponseDto.DataBean.OrderBean> orderBeans = orderService.getOrderBeanByOrderId(confirmOrderDto.getOrderId());
            if (MapUtils.isEmpty(orderBeans)) {
                log.error("paySuccessCallback_queryOrderById_faild, trackingNo:{},PaysuccessNoticeMessage:{}", LogTreadLocal.getTrackingNo(), gson.toJson(message));
                return gson.toJson(message);
            }
            QueryOrdersResponseDto.DataBean.OrderBean orderBean = orderBeans.get(OrderBeanType.SAASORDER.getCode());
            if (!PayStatus.NOT_PAY.getCode().equals(orderBean.getPayStatus())){
                return orderAdapter.sendPaySuccessNoticeMessage();
            }
            /*
             * 围餐处理
             */
            if ("meals".equals(orderBean.getSource())) {
                return orderCommonService.paySuccessCallback(message, confirmOrderDto, orderBeans);
            }
            /*
             * 微商城处理
             */
            if(OrderSourceType.SAASMALL.getCode().equals(orderBean.getSource())) {
                return mallOrderService.paySuccessCallback(message, confirmOrderDto, orderBeans);
            }
            /*
             * app订单处理
             */
            if(OrderSourceType.APP.getCode().equals(orderBean.getSource())) {
                return appOrderService.paySuccessCallback(message, confirmOrderDto, orderBeans);
            }
            //买券虚拟订单
            if(orderBean.getBizType() == 6) {
                return sellCouponOrderService.paySuccessCallback(message, confirmOrderDto, orderBeans);
            }
            //麦咖啡订单处理
            if(mcCafePartnerId.equals(orderBean.getOid())) {
                return mcCafeOrderService.paySuccessCallback(message, confirmOrderDto, orderBeans);
            }
            /*
             * 默认点餐处理
             */
            return orderService.paySuccessCallback(message, confirmOrderDto, orderBeans);
        } catch (Exception e) {
            throw e;
        } finally {
            //删除分布式锁
            redisCache.delete("saas:lockAfter:" + paySuccessKey);
        }
    }

    @Override
    public String mcCafePaySuccessCallback(PaysuccessNoticeMessage message) {
        //添加分布式锁，如果没有取得锁直接返回失败；整个方法执行完毕后会删掉该锁
        String paySuccessKey = PAY_SUCCESS_KEY + message.getTrans_id();
        if(!LockUtils.lockAfter(redisCache.getRedisTemplate(), paySuccessKey)){
            return orderAdapter.newSendPayFaileMessage();
        }
        try {
            ConfirmOrderDto confirmOrderDto = orderAdapter.convent2ConfirmOrderDto(message);
            // 通过交易号从缓存中拿订单号，如果有数据则实际订单号为其value值
            String orderId = redisCache.getValue(RedisUtil.getPaymentTransIdOrderKey(confirmOrderDto.getOrderId()));
            if (StringUtils.isNotBlank(orderId)) {
                log.info("从缓存中获取的订单数据,trackingNo:{},transId:{},orderId:{}", LogTreadLocal.getTrackingNo(), confirmOrderDto.getOrderId(), orderId);
                confirmOrderDto.setOrderId(orderId);
            }
            Map<String, QueryOrdersResponseDto.DataBean.OrderBean> orderBeans = orderService.getOrderBeanByOrderId(confirmOrderDto.getOrderId());
            if (MapUtils.isEmpty(orderBeans)) {
                log.error("paySuccessCallback_queryOrderById_faild, trackingNo:{},PaysuccessNoticeMessage:{}", LogTreadLocal.getTrackingNo(), gson.toJson(message));
                return gson.toJson(message);
            }
            QueryOrdersResponseDto.DataBean.OrderBean orderBean = orderBeans.get(OrderBeanType.SAASORDER.getCode());
            if (!PayStatus.NOT_PAY.getCode().equals(orderBean.getPayStatus())){
                return orderAdapter.sendPaySuccessNoticeMessage();
            }
            /**
             * 默认点餐处理
             */
            return mcCafeOrderService.paySuccessCallback(message, confirmOrderDto, orderBeans);
        } catch (Exception e) {
            throw e;
        } finally {
            //删除分布式锁
            redisCache.delete("saas:lockAfter:" + paySuccessKey);
        }
    }

    /**
     * APP下单，下单带商品信息，不经过购物车服务，不唤起支付
     */
    @Override
    public BaseResponse appCreateOrder(AppCreateOrderVo createOrderVo) {
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createOrderVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        if (UserLoginChannelEnum.APP.getCode().equals(assortmentCustomerInfoVo.getChannel())) {
            return appOrderService.createOrder(createOrderVo,assortmentCustomerInfoVo);
        }
        return ResponseUtil.error(ResponseResult.PARAMETER_MISSING);
    }

    /**
     * 标准点餐参数校验
     * @param createOrderVo
     * @return
     */
    private BaseResponse checkStandardParamInfo(CreateOrderVo createOrderVo){
        if(StringUtils.isEmpty(createOrderVo.getSessionId())){
            return ResponseUtil.error(ResponseResult.CREATE_ORDER_CHECK_SESSION_ERROR);
        }
        if(StringUtils.isEmpty(createOrderVo.getShopId())){
            return ResponseUtil.error(ResponseResult.CREATE_ORDER_CHECK_STORE_ERROR);
        }
        if(createOrderVo.getOrderType() == null){
            return ResponseUtil.error(ResponseResult.CREATE_ORDER_CHECK_ORDERTYPE_ERROR);
        }
        return ResponseUtil.success();
    }
}
