package cn.freemud.service.impl;

import cn.freemud.adapter.CouponAdapter;
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.UpdateReserveOrderResponseVo;
import cn.freemud.entities.dto.*;
import cn.freemud.entities.dto.promotion.CouponPromotionDto;
import cn.freemud.entities.dto.promotion.OrderBeanRequest;
import cn.freemud.entities.dto.promotion.ShoppingCartGoodsResponse;
import cn.freemud.entities.dto.shoppingCart.GetShoppingCartGoodsApportionDto;
import cn.freemud.entities.dto.shoppingCart.NewShoppingCartClearDto;
import cn.freemud.entities.dto.shoppingCart.ShoppingCartGoodsDto;
import cn.freemud.entities.vo.*;
import cn.freemud.entities.vo.encircle.CreateReserveOrderVo;
import cn.freemud.entities.vo.encircle.EmptyTableNumberVo;
import cn.freemud.entities.vo.encircle.EncircleReserveBaseVo;
import cn.freemud.entities.vo.encircle.PreviewOrderInfoVo;
import cn.freemud.enums.*;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.redis.RedisCache;
import cn.freemud.service.EncircleOrderService;
import cn.freemud.service.OrderAdapterService;
import cn.freemud.service.thirdparty.ShoppingCartClient;
import cn.freemud.service.thirdparty.StoreItemClient;
import cn.freemud.utils.AmountUtils;
import cn.freemud.utils.ResponseUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.manager.customer.AssortmentCustomerInfoManager;
import com.freemud.api.assortment.datamanager.meal.MealCacheManager;
import com.freemud.api.assortment.datamanager.meal.dto.MealNumberDto;
import com.freemud.api.assortment.datamanager.util.RedisLock;
import com.freemud.application.sdk.api.constant.ResponseResultEnum;
import com.freemud.application.sdk.api.log.ApiLog;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.enums.OrderClientType;
import com.freemud.application.sdk.api.ordercenter.enums.ProductTypeEnum;
import com.freemud.application.sdk.api.ordercenter.request.OrderExtInfoDto;
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.request.SVCCardAmountRequest;
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.response.SVCCardAmountResponse;
import com.freemud.application.sdk.api.paymentcenter.client.service.PaymentNewService;
import com.freemud.application.sdk.api.storecenter.request.GetStoreTableRequest;
import com.freemud.application.sdk.api.storecenter.response.GetStoreTableResponse;
import com.freemud.application.sdk.api.storecenter.response.StoreResponse;
import com.freemud.application.sdk.api.storecenter.service.StoreCenterService;
import com.freemud.sdk.api.assortment.order.request.order.*;
import com.freemud.sdk.api.assortment.order.response.order.CreateOrderResponse;
import com.freemud.sdk.api.assortment.order.response.order.OrderDetailResponse;
import com.freemud.sdk.api.assortment.order.response.order.QueryOrderByIdResponse;
import com.freemud.sdk.api.assortment.order.response.order.QueryOrdersResponse;
import com.freemud.sdk.api.assortment.order.service.OrderCenterSdkService;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.FastDateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @version V1.6.0
 * @Title: EncircleOrderServiceImpl
 * @Description: 简单描述下这个类是做什么用的
 * @author: qin.zhou
 * @date: 2019/8/3022:49
 * @Copyright: ${DATE.YARE} www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Slf4j
@Service
public class EncircleOrderServiceImpl implements EncircleOrderService {

    @Autowired
    private CheckOrder checkOrder;
    @Autowired
    private AssortmentCustomerInfoManager assortmentCustomerInfoManager;
    @Autowired
    private StoreCenterService storeCenterService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private StoreItemClient storeItemClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderCenterSdkService orderCenterSdkService;
    @Autowired
    private OrderAdapter orderAdapter;
    @Autowired
    private PaymentNewService paymentNewService;
    @Autowired
    private OrderCommonService orderCommonService;
    @Autowired
    private ShoppingCartClient shoppingCartClient;
    @Autowired
    private MealCacheManager mealCacheManager;
    @Autowired
    private ActivityCalculationDiscountService calculationDiscountService;
    @Autowired
    private OrderAdapterService orderAdapterService;
    @Autowired
    private CouponAdapter couponAdapter;

    private final Integer RESPONSE_SUCCESS_CODE = 100;

    private final String SESSION_KEY = "sessionKey";
    private static FastDateFormat dateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss", Locale.CHINA);

    @Override
    public BaseResponse createReserveOrder(CreateOrderVo createOrderVo) {
        //查询用户缓存信息(用户信息，用户绑定桌号信息)
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createOrderVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        //判断桌号状态
        if(mealCacheManager.getTableNumberStatus(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber())){  //此时证明当前桌号已开台
            return ResponseUtil.success();
        }
        //查询门店服务获取门店信息(营业时间，营业状态)
        createOrderVo.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
        createOrderVo.setShopId(assortmentCustomerInfoVo.getStoreId());
        StoreResponse.BizVO storeResponseDto = checkOrder.checkOrderByStore(createOrderVo, LogThreadLocal.getTrackingNo());
        //桌号状态已锁定则给出对应状态码
        GetStoreTableRequest storeTableListRequest = new GetStoreTableRequest();
        storeTableListRequest.setPartnerId(createOrderVo.getPartnerId());
        storeTableListRequest.setStoreCode(createOrderVo.getShopId());
        storeTableListRequest.setTableCode(assortmentCustomerInfoVo.getTableNumber());
        com.freemud.application.sdk.api.base.BaseResponse<GetStoreTableResponse> storeTable = storeCenterService.getStoreTable(storeTableListRequest,LogThreadLocal.getTrackingNo());
        //activeFlag 是否有效 0无效 1有效
        //orderState 点餐状态 1开台 2清台
        if(ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(),storeTable.getCode()) || storeTable.getData() == null) return ResponseUtil.error(ResponseResult.STORE_NOT_TABLE_INFO);
        if(storeTable.getData().getActiveFlag() == 0) return ResponseUtil.error(ResponseResult.QUERY_TABLESTATUS_ACTIVEFLAG_ERROR);
        if(storeTable.getData().getOrderState() == 1) {
            return ResponseUtil.success();
        }
        /**
         * 尝试获取Redis锁  ==>获取锁失败直接提示用户有人正在开台或桌号已被占用
         * 锁过期时间  24小时
         */
        boolean lock = RedisLock.getInstance(redisTemplate).lock(orderCommonService.redisLockInfo(assortmentCustomerInfoVo,RedisCacheEnum.CREATERESERVEORDER_LOCKKEY_PREFIX),60*60*24);
        if(!lock) return ResponseUtil.error(ResponseResult.ENCIRCLEORDER_TABLENUMBER_LOCK);
        try {
            //查询商品服务(获取基本的商品信息:餐具等)
            GetShopDishWareProductDto getShopDishWareProductDto = new GetShopDishWareProductDto();
            getShopDishWareProductDto.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
            getShopDishWareProductDto.setStoreId(assortmentCustomerInfoVo.getStoreId());
            getShopDishWareProductDto.setChannel(OrderSourceType.SAAS.getCode());
            ShopBaseResponseDto<List<ProductListDto.DataBean>> dishWareProductList = storeItemClient.findDishWareProductList(getShopDishWareProductDto);
            /*if(dishWareProductList == null || ObjectUtils.notEqual(dishWareProductList.getErrcode(),RESPONSE_SUCCESS_CODE) || dishWareProductList.getData() == null || CollectionUtils.isEmpty(dishWareProductList.getData())){
                //查询门店服务餐具错误  返回开台失败  抛出业务异常
                throw  new ServiceException(ResponseResult.QUERY_STORE_TABLEWARE_ERROR);
            }*/
            CreateOrderResponse createOrderResponse = this.createGroupOrderInfo(createOrderVo,assortmentCustomerInfoVo,dishWareProductList,storeResponseDto);
            if(createOrderResponse == null || createOrderResponse.getErrcode() != 100){
                //创建订单错误  返回开台失败  抛出业务异常
                throw new ServiceException(ResponseResult.CREATE_GROUP_ORDER_ERROR_START);
            }
            //缓存该桌用餐人数以及餐具数量金额
            MealNumberDto mealNumberDto = new MealNumberDto();
            mealNumberDto.setPeopleNumber(createOrderVo.getPeopleNumber());
            mealNumberDto.setDinner(createOrderVo.getPeopleNumber());
            if(dishWareProductList.getData() != null && CollectionUtils.isNotEmpty(dishWareProductList.getData())){
                List<ProductListDto.DataBean> dishProductList = dishWareProductList.getData();
                List<ProductListDto.DataBean> availableDishProductList = dishProductList.stream().filter(each -> each.getStatus() == 2).collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(availableDishProductList)){
                    mealNumberDto.setUnitPrice(availableDishProductList.stream().mapToInt(var->var.getOriginalPrice().intValue()).sum());
                }
            }
            mealCacheManager.saveDinnerNumber(mealNumberDto,assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
            //--清台时同步清除
            mealCacheManager.saveMealOrder(createOrderResponse.getData().getOid(),assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
            //避免多次查询门店，当该桌号被锁定，则缓存占有当前桌号  --清台时同步清除
            mealCacheManager.setTableNumberStatus(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
            //调用门店服务锁定桌号
            com.freemud.application.sdk.api.base.BaseResponse tableNumberStatus = orderCommonService.changeTableNumberStatus(assortmentCustomerInfoVo,1);
            if(ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(),tableNumberStatus.getCode())) {
                //调用门店服务锁定桌号错误
                throw  new ServiceException(ResponseResult.CALL_STORE_CHANGE_TABLENUMBER_ERROR);
            }
        } catch (Exception e) {
            //开台异常直接清台
            ClearTableRequest clearTableRequest = new ClearTableRequest();
            clearTableRequest.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
            clearTableRequest.setStoreId(assortmentCustomerInfoVo.getStoreId());
            clearTableRequest.setTableNumber(assortmentCustomerInfoVo.getTableNumber());
            clearTableRequest.setUserId(assortmentCustomerInfoVo.getMemberId());
            clearTableRequest.setOpClearTableEnum(ClearTableRequest.OpClearTableEnum.closeOrder);
            clearTableRequest.setOperator(assortmentCustomerInfoVo.getNickName());
            orderCenterSdkService.clearTableNumber(clearTableRequest);
            throw e;
        }finally {
            //释放锁
            redisTemplate.delete(orderCommonService.redisLockInfo(assortmentCustomerInfoVo,RedisCacheEnum.CREATERESERVEORDER_LOCKKEY_PREFIX));
        }
        /**
         * 开台成功
         */
        return ResponseUtil.success();
    }

    /**
     * 创建预订单
     * @return
     */
    private CreateOrderResponse createGroupOrderInfo(CreateOrderVo createOrderVo,AssortmentCustomerInfoVo assortmentCustomerInfoVo,ShopBaseResponseDto<List<ProductListDto.DataBean>> dishWareProductList,StoreResponse.BizVO storeResponseDto){
        //组装预订单(未支付订单)信息 调用订单订单基础服务创建预订单--调用订单基础服务新开接口
        AssortmentGroupCreateOrderRequest groupCreateOrderRequest = new AssortmentGroupCreateOrderRequest();
        groupCreateOrderRequest.setDinersNumber(createOrderVo.getPeopleNumber());
        groupCreateOrderRequest.setCompanyId(assortmentCustomerInfoVo.getPartnerId());
        groupCreateOrderRequest.setShopId(assortmentCustomerInfoVo.getStoreId());
        groupCreateOrderRequest.setShopName(storeResponseDto.getStoreName());
        groupCreateOrderRequest.setShopNameEn(storeResponseDto.getStoreNameEn());
        groupCreateOrderRequest.setBarCounter(assortmentCustomerInfoVo.getTableNumber());
        groupCreateOrderRequest.setOrderClient(OrderClientType.WAI_MEAL.getIndex()); //默认围餐
        //开台不存用户信息
        /*groupCreateOrderRequest.setUserId(assortmentCustomerInfoVo.getMemberId());
        groupCreateOrderRequest.setUserName(assortmentCustomerInfoVo.getNickName());*/
        List<CreateOrderProductRequest> orderProductRequests = new ArrayList<>();
        if(dishWareProductList != null && CollectionUtils.isNotEmpty(dishWareProductList.getData())){
            dishWareProductList.getData().stream().filter(var->var.getIsDishware() == 1).forEach(dataBean->{
                CreateOrderProductRequest createOrderProductRequest = new CreateOrderProductRequest();
                createOrderProductRequest.setNumber(createOrderVo.getPeopleNumber());
                createOrderProductRequest.setProductId(dataBean.getPid());
                createOrderProductRequest.setProductName(dataBean.getName());
                createOrderProductRequest.setCustomerCode(dataBean.getCustomerCode());
                createOrderProductRequest.setProductCode(dataBean.getBarcode());
                createOrderProductRequest.setPrice(dataBean.getOriginalPrice());
                createOrderProductRequest.setSalePrice(dataBean.getFinalPrice());
                createOrderProductRequest.setPicture(dataBean.getPicture());
                createOrderProductRequest.setOpid(1);
                createOrderProductRequest.setProductType(ProductTypeEnum.TABLEWARE_PRODUCT.getCode());
                createOrderProductRequest.setCategoryId(dataBean.getCategory());
                createOrderProductRequest.setCategoryName(dataBean.getCategoryName());
                createOrderProductRequest.setIgnoreProductPrice(1);
                createOrderProductRequest.setTotalDiscountAmount(0L);
                createOrderProductRequest.setHasStockProudct(dataBean.getStockLimit() == 2);
                OrderProductAddInfoDto orderProductAddInfoDto = new OrderProductAddInfoDto();
                if(CollectionUtils.isNotEmpty(dataBean.getProductAttributeGroupList())){
                    orderProductAddInfoDto.setAttributeNames(dataBean.getProductAttributeGroupList().get(0).getAttributeName());
                }
                createOrderProductRequest.setAddInfo(JSON.toJSONString(orderProductAddInfoDto));
                orderProductRequests.add(createOrderProductRequest);
            });
        }
        groupCreateOrderRequest.setProducts(orderProductRequests);
        groupCreateOrderRequest.setOperator(assortmentCustomerInfoVo.getNickName() == null ? "围餐": assortmentCustomerInfoVo.getNickName());
        // 扩展字段添加sessionKey
        if (StringUtils.isNotBlank(createOrderVo.getSessionKey())) {
            groupCreateOrderRequest.setExtInfo(JSONObject.toJSONString(ImmutableMap.of(SESSION_KEY, createOrderVo.getSessionKey())));
        }
        return orderCenterSdkService.createGroupOrder(groupCreateOrderRequest);
    }


    @Override
    public BaseResponse updateReserveOrder(CreateReserveOrderVo createReserveOrderVo) {
        //获取缓存(用户信息，桌号信息，桌号与订单号信息)
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createReserveOrderVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        //判断订单是否已经唤起支付
        boolean prePayLock = mealCacheManager.getOrderCreatePreParmentLock(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        if(prePayLock){
            return ResponseUtil.error(ResponseResult.ORDER_PRE_PAYMENT_LOCK);
        }
        //查询当前桌号绑定的订单
        String orderId = mealCacheManager.getMealOrder(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        if(StringUtils.isBlank(orderId)){
            return ResponseUtil.error(ResponseResult.ORDER_QUERYORDER_ERROR);
        }
        //获取redis锁，只有第一个抢占到锁的才可以操作下单，未抢占到锁则给出提示正在有人下单，请稍等
        /**
         * 尝试获取Redis锁  ==>获取锁失败直接提示用户有人正在下单
         * 锁过期时间  24小时
         */
        boolean lock = RedisLock.getInstance(redisTemplate).lock(orderCommonService.redisLockInfo(assortmentCustomerInfoVo,RedisCacheEnum.ORDER_PLUS_DISH_LOCKKEY_PREFIX),60*60*24);
        if(!lock) return ResponseUtil.error(ResponseResult.ENCIRCLEORDER_UPDATE_ORDER_LOCK);
        NewShoppingCartClearDto shoppingCartClearDto = new NewShoppingCartClearDto();
        shoppingCartClearDto.setSessionId(createReserveOrderVo.getSessionId());
        shoppingCartClearDto.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
        shoppingCartClearDto.setShopId(assortmentCustomerInfoVo.getStoreId());
        shoppingCartClearDto.setAppId(assortmentCustomerInfoVo.getWxAppId());
        shoppingCartClearDto.setOperationType(2);
        try {
            //查询购物车商品信息  根据购物车version
            // 通过购物车获取优惠信息
            ShoppingCartInfoRequestVo shoppingCartInfoRequestVo = ShoppingCartInfoRequestVo.builder()
                    .partnerId(assortmentCustomerInfoVo.getPartnerId())
                    .shopId(assortmentCustomerInfoVo.getStoreId())
                    .version(createReserveOrderVo.getVersion())
                    .sessionId(assortmentCustomerInfoVo.getSessionId())
                    .orderType(CreateOrderType.COLLECT_GOODS.getCode())
                    .flag(CouponFlag.NO.getCode())
                    .carVer(createReserveOrderVo.getCarVer())
                    .appId(assortmentCustomerInfoVo.getWxAppId())
                    .build();
            GetShoppingCartGoodsApportionDto requestDto = new GetShoppingCartGoodsApportionDto();
            requestDto.setShoppingCartInfoRequestVo(shoppingCartInfoRequestVo);
            cn.freemud.base.entity.BaseResponse<ShoppingCartGoodsDto> apportionResponse = shoppingCartClient.getShoppingCartGoodsApportionNew(requestDto);
            if (!ObjectUtils.equals(ResponseCodeConstant.RESPONSE_SUCCESS_STR, apportionResponse.getCode())) {
                return ResponseUtil.error(ResponseResult.SHOPPING_CART_GETINFO_ERROR.getCode(),apportionResponse.getMessage());
            }
            if (apportionResponse.getResult() == null || CollectionUtils.isEmpty(apportionResponse.getResult().getProducts())) {
                return ResponseUtil.error(ResponseResult.SHOPPING_CART_GETINFO_INVAILD);
            }
            ShoppingCartGoodsDto shoppingCartGoodsDto = apportionResponse.getResult();
            AssortmentSdkUpdateOrderProductInfoRequest request = orderAdapter.conventShoppingCartGoodsDtoByUpdate(shoppingCartGoodsDto, assortmentCustomerInfoVo, orderId,
                    createReserveOrderVo.getRepastNumber(), assortmentCustomerInfoVo.getNickName(), false);
            //修改订单信息
            OrderDetailResponse baseOrderResponse = orderCenterSdkService.updateOrderItem(request);
            //根据购物车version调用购物车sdk删除购物车版本缓存信息
            if(ObjectUtils.notEqual(baseOrderResponse.getErrcode(),RESPONSE_SUCCESS_CODE)){
                return ResponseUtil.error(ResponseResult.ORDER_EDIT_ERROR);
            }
            shoppingCartClearDto.setOperationType(1);
        } catch (Exception e) {
            e.printStackTrace();
            ApiLog.info("EncircleOrderService updateReserveOrder error:{}", Throwables.getStackTraceAsString(e));
            throw new ServiceException(ResponseResult.UPDATE_ORDER_INFO_ERROR);
        }finally {
            //释放锁
            redisTemplate.delete(orderCommonService.redisLockInfo(assortmentCustomerInfoVo,RedisCacheEnum.ORDER_PLUS_DISH_LOCKKEY_PREFIX));
            try {
                ShoppingCartBaseResponse cartBaseResponse = shoppingCartClient.clearShoppingCart(shoppingCartClearDto);
                if(cartBaseResponse == null || ObjectUtils.notEqual(cartBaseResponse.getCode(),RESPONSE_SUCCESS_CODE)){
                    ApiLog.info("clearShoppingCart error:{}", JSON.toJSONString(cartBaseResponse));
                    return ResponseUtil.error(ResponseResult.CLEAR_SHOPPING_INFO_ERROR);
                }
            } catch (Exception e) {
                ApiLog.info("EncircleOrderService clearShopping error:{}",e.getStackTrace());
                throw new ServiceException(ResponseResult.CLEAR_SHOPPING_INFO_SYSTEM_ERROR);
            }
        }
        //下单成功，保存下单版本号
        Integer orderUpdateVer = mealCacheManager.incrementOrderUpdateVersion(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        UpdateReserveOrderResponseVo updateReserveOrderResponseVo = new UpdateReserveOrderResponseVo();
        updateReserveOrderResponseVo.setOrderUpdateVer(orderUpdateVer);
        return ResponseUtil.success(updateReserveOrderResponseVo);
    }

    @Override
    public BaseResponse queryOrderInfo(CreateReserveOrderVo createReserveOrderVo) {
        //获取缓存(用户信息，桌号信息，桌号与订单号信息)
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createReserveOrderVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        //查询当前桌号绑定的订单
        String orderId = mealCacheManager.getMealOrder(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        if(StringUtils.isBlank(orderId)){
            return ResponseUtil.error(ResponseResult.ORDER_QUERYORDER_ERROR);
        }
        //查询订单信息
        BaseQueryOrderRequest baseQueryOrderRequest = new BaseQueryOrderRequest();
        baseQueryOrderRequest.setOrderId(orderId);
        baseQueryOrderRequest.setTrackingNo(LogTreadLocal.getTrackingNo());
        QueryOrderByIdResponse queryOrderByIdResponse = orderCenterSdkService.queryOrderById(baseQueryOrderRequest);
        if (!RESPONSE_SUCCESS_CODE.equals(queryOrderByIdResponse.getErrcode()) || queryOrderByIdResponse.getData() == null) {
            return ResponseUtil.error(ResponseResult.ORDER_QUERYORDER_ERROR);
        }

        List<QueryOrderResponseVo> queryOrderResponseVos = orderAdapter.convent2QueryOrderResponseVos(Collections.singletonList(queryOrderByIdResponse.getData()),assortmentCustomerInfoVo.getWxAppId(), assortmentCustomerInfoVo.getIappId());
        PreviewOrderInfoVo previewOrderInfoVo = orderAdapter.conventQueryOrderByIdResponse(queryOrderResponseVos.get(0));
        previewOrderInfoVo.setOid(queryOrderByIdResponse.getData().getOid());
        previewOrderInfoVo.setTableNumber(assortmentCustomerInfoVo.getTableNumber());

        // 如果已经调用了预支付则不再进行促销计算
        boolean prePayLock = mealCacheManager.getOrderCreatePreParmentLock(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        Integer payIsArouseStatus = 1;
        if (!prePayLock) {
            payIsArouseStatus = 0;
            OrderBeanRequest orderBeanRequest = orderAdapter.conventOrderBeanRequest(queryOrderByIdResponse.getData(), assortmentCustomerInfoVo,createReserveOrderVo);
            CouponPromotionDto couponPromotionDto = couponAdapter.getCouponPromotionDto(orderBeanRequest, createReserveOrderVo.getCouponCode(), createReserveOrderVo.getActivityCode(), CouponFlag.YES.getCode());
            //新增是否需要分摊计算优化金额，满减和优化券不进行优惠分摊
            ShoppingCartGoodsResponse shoppingCartGoodsResponse = calculationDiscountService.updateDiscountApportion(orderBeanRequest, couponPromotionDto,false);
            calculationDiscountService.updatePreviewOrderInfoVo(previewOrderInfoVo, shoppingCartGoodsResponse);
        }
        //是否唤起支付
        previewOrderInfoVo.setPayIsArouseStatus(payIsArouseStatus);
        //校验返回的订单信息，如包含称重菜单但未称重则不走后续流程直接返回当前订单详细信息，不计算金额
        Integer payLicenceStatus = 0;
        if(!orderCommonService.queryExistWeightNoNum(queryOrderByIdResponse.getData())){
            payLicenceStatus = 0; //不可支付
        }else{
            payLicenceStatus = 1;  //可支付
        }
        previewOrderInfoVo.setPayLicenceStatus(payLicenceStatus);
        //下单成功，保存下单版本号
        Integer orderUpdateVer = mealCacheManager.getIncrementOrderUpdateVersion(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        previewOrderInfoVo.setOrderUpdateVer(orderUpdateVer);
        previewOrderInfoVo.setCreateOrderTime(dateFormat.format(new Date(queryOrderByIdResponse.getData().getGmtCreate())));
        //本次版本不考虑优惠券的使用
        return ResponseUtil.success(previewOrderInfoVo);
    }

    @Override
    public BaseResponse previewOrderInfoSvcCheck(CreateReserveOrderVo createReserveOrderVo) {
        if (StringUtils.isBlank(createReserveOrderVo.getCardCode())) {
            return ResponseUtil.error(ResponseResult.PARAMETER_MISSING);
        }
        BaseResponse<PreviewOrderInfoVo> baseResponse = queryOrderInfo(createReserveOrderVo);
        if (baseResponse == null || !ResponseResult.SUCCESS.getCode().equals(baseResponse.getCode())) {
            return baseResponse;
        }
        PreviewOrderInfoVo shoppingCartGoodsResponseVo = baseResponse.getResult();
        String partnerId = createReserveOrderVo.getPartnerId();
        //SVC卡支付
        SVCCardPay(createReserveOrderVo.getCardCode(), partnerId, shoppingCartGoodsResponseVo);
        return ResponseUtil.success(shoppingCartGoodsResponseVo);
    }


    /**
     * 储值卡支付余额校验
     */
    private void SVCCardPay(String cardCode,  String partnerId,
                            PreviewOrderInfoVo previewOrderInfoVo) {
        if (StringUtils.isBlank(cardCode)) {
            return;
        }
        Integer orderAmount = previewOrderInfoVo.getAmount().intValue();
        String trackingNo = LogThreadLocal.getTrackingNo();
        SVCCardAmountRequest request = new SVCCardAmountRequest();
        request.setPartnerId(partnerId);
        request.setCardCodes(Arrays.asList(cardCode));
        //查询svc卡金额
        com.freemud.application.sdk.api.base.BaseResponse<SVCCardAmountResponse> response = paymentNewService.querySVCCardAmount(request, trackingNo);
        if (response == null) {
            throw new ServiceException(ResponseResult.SYSTEM_BUSINESS_ERROR);
        }
        if (response.getData() == null || response.getData().getData() == null || response.getData().getData().getCardSimpleInfos().size() > 1) {
            throw new ServiceException(ResponseResult.USER_SVC_CARD_ERROR);
        }
        Integer amount1 = response.getData().getData().getCardSimpleInfos().get(0).getAmount();
        Integer vamount = response.getData().getData().getCardSimpleInfos().get(0).getVamount();
        if (orderAmount > amount1 + vamount) {
            throw new ServiceException(ResponseResult.USER_SVC_CARD_AMOUNT_DEFICIENCY);
        }
        BigDecimal bigDecimal = new BigDecimal(orderAmount);
        String amountStr = bigDecimal.divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        previewOrderInfoVo.setAmount(0L);
        previewOrderInfoVo.setSvcDiscountDesc("储值卡支付￥" + amountStr);
    }


    @Override
    public BaseResponse createPrepaymentOrder(CreateReserveOrderVo createReserveOrderVo) {
       //获取缓存(用户信息，桌号信息，桌号与订单号信息)
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(createReserveOrderVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        String orderId = mealCacheManager.getMealOrder(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        if(StringUtils.isBlank(orderId)){
            return ResponseUtil.error(ResponseResult.ORDER_QUERYORDER_ERROR);
        }
        // 校验svc卡
        checkOrder.checkCardCode(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getMemberId(), createReserveOrderVo.getCardCode());
        CreateOrderResponseVo orderResponseVo = null;
        //拉取订单详细信息
        BaseQueryOrderRequest baseQueryOrderRequest = new BaseQueryOrderRequest();
        baseQueryOrderRequest.setOrderId(orderId);
        baseQueryOrderRequest.setTrackingNo(LogTreadLocal.getTrackingNo());
        QueryOrderByIdResponse queryOrderByIdResponse = orderCenterSdkService.queryOrderById(baseQueryOrderRequest);
        //判断订单中是否存在未称重商品
        if(!orderCommonService.queryExistWeightNoNum(queryOrderByIdResponse.getData())){
            return ResponseUtil.error(ResponseResult.ORDER_INFO_NOT_WEIGHT_ERROR);
        }
        //判断订单支付状态 订单状态已支付则返回已支付
        QueryOrdersResponse.DataBean.OrderBean orderBean = queryOrderByIdResponse.getData();
        if(PayStatus.HAVE_PAID.getCode().equals(orderBean.getPayStatus()) || OrderStatus.COMPLETE.getCode().equals(orderBean.getStatus())){
            return ResponseUtil.success(ResponseResult.ENCIRCLEORDER_PRE_PAYMENT_SUCCESS);
        }

        //获取redis锁，只有第一个抢占到锁的才可以操作下单，未抢占到锁则给出提示正在有人支付，请稍等
        /**
         * 尝试获取Redis锁  ==>获取锁失败直接提示用户有人正在支付
         * 锁过期时间  24小时
         */
        boolean lock = RedisLock.getInstance(redisTemplate).lock(orderCommonService.redisLockInfo(assortmentCustomerInfoVo,RedisCacheEnum.CREATE_PRE_PAYMENTORDER_LOCKKEY_PREFIX),60*60*24);
        if(!lock) return ResponseUtil.error(ResponseResult.ENCIRCLEORDER_PRE_PAYMENT_LOCK);
        // 是否需要促销计算，一个订单只能促销计算一遍
        boolean updateDiscountApportion = false;
        try {
            // 判断订单是否已经唤起支付
            boolean prePayLock = mealCacheManager.getOrderCreatePreParmentLock(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
            ShoppingCartGoodsResponse shoppingCartGoodsResponse = null;
            if (!prePayLock) {
                OrderBeanRequest orderBeanRequest = orderAdapter.conventOrderBeanRequest(queryOrderByIdResponse.getData(), assortmentCustomerInfoVo,createReserveOrderVo);
                CouponPromotionDto couponPromotionDto = couponAdapter.getCouponPromotionDto(orderBeanRequest, createReserveOrderVo.getCouponCode(), createReserveOrderVo.getActivityCode(), CouponFlag.YES.getCode());
                shoppingCartGoodsResponse = calculationDiscountService.updateDiscountApportion(orderBeanRequest, couponPromotionDto,true);
            }
            boolean isUpdateAccounts = CollectionUtils.isEmpty(queryOrderByIdResponse.getData().getAccountList());
            AssortmentSdkUpdateOrderProductInfoRequest request = orderAdapter.conventShoppingPromotionInfo(shoppingCartGoodsResponse, queryOrderByIdResponse, assortmentCustomerInfoVo, isUpdateAccounts,createReserveOrderVo, prePayLock);
            //修改订单信息
            OrderDetailResponse baseOrderResponse = orderCenterSdkService.updateOrderItem(request);
            if(baseOrderResponse == null || ObjectUtils.notEqual(baseOrderResponse.getErrcode(),RESPONSE_SUCCESS_CODE)){
                return ResponseUtil.error(ResponseResult.PREVIEWORDER_UPDATE_ORDERPRICE_ERROR);
            }
            // 促销更新成功
            if(shoppingCartGoodsResponse != null) {
                updateDiscountApportion = true;
            }

            orderResponseVo = new CreateOrderResponseVo();
            orderResponseVo.setOrderUpdateVer(mealCacheManager.getIncrementOrderUpdateVersion(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber()));
            //判断订单是否发生变更
            if(ObjectUtils.notEqual(mealCacheManager.getIncrementOrderUpdateVersion(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber()),createReserveOrderVo.getOrderUpdateVer())){
                 return ResponseUtil.error(ResponseResult.ORDER_COMPAR_PRODUCTS_CHANGE.getCode(),
                         ResponseResult.ORDER_COMPAR_PRODUCTS_CHANGE.getMessage() + AmountUtils.changeF2Y(baseOrderResponse.getData().getAmount()).toPlainString(), orderResponseVo);
            }

            OrderExtInfoDto extInfo = JSONObject.parseObject(orderBean.getExtInfo(), OrderExtInfoDto.class);
            //判断当前订单是否存在预支付订单
            if(extInfo != null && StringUtils.isNotEmpty(extInfo.getPrePayTransId()) && StringUtils.isNotEmpty(extInfo.getFmId())){
                //订单状态未支付且存在预支付订单：
                // 1.查询预支付订单支付状态
                PaymentQueryRequest paymentQueryRequest = new PaymentQueryRequest();
                paymentQueryRequest.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
                paymentQueryRequest.setStoreId(assortmentCustomerInfoVo.getStoreId());
                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())){
                    return ResponseUtil.error(ResponseResultEnum.PAY_BACKEND_QUERY_DETAIL_ERROR.getCode(),ResponseResultEnum.PAY_BACKEND_QUERY_DETAIL_ERROR.getMessage(),null);
                }
                //判断当前预支付订单是否已经支付成功
                if(ObjectUtils.equals(TradeState.SUCCESS.getCode(),queryResponseBaseResponse.getData().getTradeState())){
                    return ResponseUtil.error(ResponseResult.ENCIRCLEORDER_PRE_PAYMENT_SUCCESS);
                }
                // 3.取消前一个预支付订单  调用支付取消预支付订单,如果预支付订单已经取消了再调用取消预支付订单接口会报错的
                if(ObjectUtils.equals(TradeState.NOTPAY.getCode(), queryResponseBaseResponse.getData().getTradeState())) {
                    PaymentCloseUnifiedOrderRequest closeUnifiedOrderRequest = new PaymentCloseUnifiedOrderRequest();
                    closeUnifiedOrderRequest.setFmId(extInfo.getFmId());
                    closeUnifiedOrderRequest.setVer("2");
                    closeUnifiedOrderRequest.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
                    closeUnifiedOrderRequest.setStoreId(assortmentCustomerInfoVo.getStoreId());
                    com.freemud.application.sdk.api.base.BaseResponse<PaymentCloseUnifiedOrderResponse> cancelNewUnifiedOrder = paymentNewService.cancelNewUnifiedOrder(closeUnifiedOrderRequest,LogThreadLocal.getTrackingNo());
                    if(ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(),cancelNewUnifiedOrder.getCode())){
                        return ResponseUtil.error(ResponseResult.ENCIRCLEORDER_PRE_PAYMENT_CLOSE_FAILED);
                    }
                }
            }
            //此处使用订单修改金额后的金额数据显示支付
            queryOrderByIdResponse.getData().setAmount(baseOrderResponse.getData().getAmount());
            //调用预支付
            orderResponseVo = orderCommonService.createPrePaymentOrder(baseOrderResponse.getData(),assortmentCustomerInfoVo,assortmentCustomerInfoVo.getPartnerId(),0,createReserveOrderVo.getCardCode());
            if(orderResponseVo != null){
                if(orderResponseVo.getPaySuccess()){
                    //如果是商品券支付0元，调用回调接口
                    PaysuccessNoticeMessage message = new PaysuccessNoticeMessage();
                    message.setResult_code(100);
                    message.setOut_trade_no(orderResponseVo.getFmId());
                    message.setTrans_id(orderResponseVo.getOid());
                    message.setTotal_fee(0);
                    message.setOpenid(assortmentCustomerInfoVo.getOpenId());
                    message.setPlatform_coupon(0);
                    message.setMerchant_coupon(0);
                    orderAdapterService.paySuccessCallback(message);
                }
            }else{
                return ResponseUtil.error(ResponseResultEnum.PAY_UNIFIED_ORDER_ERROR.getCode(), ResponseResultEnum.PAY_UNIFIED_ORDER_ERROR.getMessage(), null);
            }
        } catch (Exception e) {
           throw new ServiceException(ResponseResult.PAY_BACKEND_CONFIG_ERROR);
        }finally {
            //释放锁
            redisTemplate.delete(orderCommonService.redisLockInfo(assortmentCustomerInfoVo,RedisCacheEnum.CREATE_PRE_PAYMENTORDER_LOCKKEY_PREFIX));
            if(orderResponseVo != null && Objects.equals(orderResponseVo.getPaySuccess(), false) && updateDiscountApportion) {
                //记录订单支付状态，防止用户在唤起支付后继续下单,同时也防止重复进行促销计算
                mealCacheManager.setOrderCreatePreParmentLock(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
            }

        }
        return ResponseUtil.success(orderResponseVo);
    }


    @Override
    public BaseResponse emptyTableNumber(EmptyTableNumberVo emptyTableNumberVo) {

        //查询当前桌号是否绑定订单，当前桌号绑定订单则默认关闭当前订单

        //调用购物车sdk清楚购物车信息

        //调用门店服务解除桌号开台状态

        //调用sdk清楚缓存桌号开台状态

        return null;
    }


    @Override
    public BaseResponse queryTableNumberStatus(EncircleReserveBaseVo encircleReserveBaseVo) {
        //查询用户缓存信息(用户信息，用户绑定桌号信息)
        AssortmentCustomerInfoVo assortmentCustomerInfoVo = assortmentCustomerInfoManager.getCustomerInfoByObject(encircleReserveBaseVo.getSessionId());
        if (assortmentCustomerInfoVo == null || StringUtils.isEmpty(assortmentCustomerInfoVo.getMemberId())) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        //判断用户是否绑定桌号
        if(StringUtils.isBlank(assortmentCustomerInfoVo.getTableNumber())){
            return ResponseUtil.error(ResponseResult.ORDER_TABLE_BINDING_ERROR);
        }
        QueryTableStatusReponseVo queryTableStatusReponseVo = new QueryTableStatusReponseVo();
        //桌号状态已锁定则给出对应状态码  --查询门店服务
        GetStoreTableRequest storeTableListRequest = new GetStoreTableRequest();
        storeTableListRequest.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
        storeTableListRequest.setStoreCode(assortmentCustomerInfoVo.getStoreId());
        storeTableListRequest.setTableCode(assortmentCustomerInfoVo.getTableNumber());
        com.freemud.application.sdk.api.base.BaseResponse<GetStoreTableResponse> storeTable = storeCenterService.getStoreTable(storeTableListRequest,LogThreadLocal.getTrackingNo());
        if(ObjectUtils.notEqual(ResponseResult.SUCCESS.getCode(),storeTable.getCode()) || storeTable.getData() == null) return ResponseUtil.error(ResponseResult.STORE_NOT_TABLE_INFO);
        if(storeTable.getData().getActiveFlag() == 0) return ResponseUtil.error(ResponseResult.QUERY_TABLESTATUS_ACTIVEFLAG_ERROR);
        if(storeTable.getData().getOrderState() == 2){
            queryTableStatusReponseVo.setTableNumberStatus(false);
            return ResponseUtil.success(queryTableStatusReponseVo);
        }
        //查询有订单返回订单信息
        String orderId = mealCacheManager.getMealOrder(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber());
        boolean tableNumberStatus = mealCacheManager.getTableNumberStatus(assortmentCustomerInfoVo.getPartnerId(), assortmentCustomerInfoVo.getStoreId(), assortmentCustomerInfoVo.getTableNumber());
        // 桌号状态为未开台或缓存失效
        if(!tableNumberStatus) {
            //订单还存在的话，则进行清台
            if(!StringUtils.isEmpty(orderId)) {
                //开始清台，关闭订单
                ClearTableRequest clearTableRequest = new ClearTableRequest();
                clearTableRequest.setPartnerId(assortmentCustomerInfoVo.getPartnerId());
                clearTableRequest.setStoreId(assortmentCustomerInfoVo.getStoreId());
                clearTableRequest.setTableNumber(assortmentCustomerInfoVo.getTableNumber());
                clearTableRequest.setUserId(assortmentCustomerInfoVo.getMemberId());
                clearTableRequest.setOpClearTableEnum(ClearTableRequest.OpClearTableEnum.closeOrder);
                clearTableRequest.setOperator(assortmentCustomerInfoVo.getNickName());
                orderCenterSdkService.clearTableNumber(clearTableRequest);
            }
            queryTableStatusReponseVo.setTableNumberStatus(false);
            return ResponseUtil.success(queryTableStatusReponseVo);
        }
        //桌台为开台状态,订单不能为空
        if(StringUtils.isBlank(orderId)){
            return ResponseUtil.error(ResponseResult.ORDER_QUERYORDER_ERROR);
        }
        //查询订单信息
        BaseQueryOrderRequest baseQueryOrderRequest = new BaseQueryOrderRequest();
        baseQueryOrderRequest.setOrderId(orderId);
        baseQueryOrderRequest.setTrackingNo(LogTreadLocal.getTrackingNo());
        QueryOrderByIdResponse queryOrderByIdResponse = orderCenterSdkService.queryOrderById(baseQueryOrderRequest);
        queryTableStatusReponseVo = orderAdapter.conventTableStatusInfoByOrderInfo(queryOrderByIdResponse);
        queryTableStatusReponseVo.setTableNumberStatus(mealCacheManager.getTableNumberStatus(assortmentCustomerInfoVo.getPartnerId(),assortmentCustomerInfoVo.getStoreId(),assortmentCustomerInfoVo.getTableNumber()));
        return ResponseUtil.success(queryTableStatusReponseVo);
    }

}
