package com.bonus.canteen.core.order.android.business.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.bonus.canteen.core.account.v3.api.vo.AccInfoServiceV3Api;
import com.bonus.canteen.core.allocation.api.AllocStallApi;
import com.bonus.canteen.core.common.constant.NuclearModeEnum;
import com.bonus.canteen.core.common.page.PageVO;
import com.bonus.canteen.core.common.utils.JavaxValidateUtils;
import com.bonus.canteen.core.common.utils.LeCodeUtil;
import com.bonus.canteen.core.customer.vo.CustPayVO;
import com.bonus.canteen.core.device.api.DeviceApi;
import com.bonus.canteen.core.order.android.business.OrderDishesAndroidBusiness;
import com.bonus.canteen.core.order.android.business.OrderInfoAndroidBusiness;
import com.bonus.canteen.core.order.android.dto.OrderInfoAndroidQueryDTO;
import com.bonus.canteen.core.order.android.dto.OrderListAndroidCustQueryDTO;
import com.bonus.canteen.core.order.android.dto.OrderListAndroidQueryDTO;
import com.bonus.canteen.core.order.android.dto.OrderStatAndroidQueryDTO;
import com.bonus.canteen.core.order.android.vo.OrderDetailAndroidVO;
import com.bonus.canteen.core.order.android.vo.OrderInfoAndroidVO;
import com.bonus.canteen.core.order.android.vo.OrderListAndroidVO;
import com.bonus.canteen.core.order.client.OrderModuleClient;
import com.bonus.canteen.core.order.client.po.CustPayInfoQueryParam;
import com.bonus.canteen.core.order.common.constants.DetailStateEnum;
import com.bonus.canteen.core.order.common.constants.OrderStateEnum;
import com.bonus.canteen.core.order.common.model.OrderDelivery;
import com.bonus.canteen.core.order.common.model.OrderInfo;
import com.bonus.canteen.core.order.common.query.OrderQueryHelper;
import com.bonus.canteen.core.order.common.service.OrderDeliveryService;
import com.bonus.canteen.core.order.common.service.OrderDetailService;
import com.bonus.canteen.core.order.common.service.OrderInfoService;
import com.bonus.canteen.core.order.common.vo.OrderIdDateVO;
import com.bonus.canteen.core.order.custom.OrderCustomBusiness;
import com.bonus.canteen.core.order.deprecated.dto.OrdLeCodeDTO;
import com.bonus.canteen.core.order.utils.LeNumUtil;
import com.bonus.canteen.core.order.web.business.OrderWebBusiness;
import com.bonus.canteen.core.order.web.dto.OrderUserPermissionDTO;
import com.bonus.canteen.core.report.api.ReportOrderApi;
import com.bonus.canteen.core.report.api.dto.DeviceOrderDishesSumQueryDTO;
import com.bonus.canteen.core.report.api.dto.ReportOrderSumQueryDTO;
import com.bonus.canteen.core.report.api.vo.DeviceOrderDishesSumVO;
import com.bonus.canteen.core.report.api.vo.ReportDeviceOrderSumVO;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.houqin.i18n.I18n;
import com.github.pagehelper.page.PageMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class OrderInfoAndroidBusinessImpl implements OrderInfoAndroidBusiness {
   private static final Logger log = LoggerFactory.getLogger(OrderInfoAndroidBusinessImpl.class);
   @Autowired
   @Lazy
   protected OrderInfoService orderInfoService;
   @Autowired
   @Lazy
   protected OrderDetailService orderDetailService;
   @Autowired
   @Lazy
   protected OrderDeliveryService orderDeliveryService;
   @Autowired
   @Lazy
   protected OrderWebBusiness orderWebBusiness;
   @Autowired
   @Lazy
   protected OrderDishesAndroidBusiness orderDishesAndroidBusiness;
   @Autowired
   @Lazy
   protected OrderCustomBusiness orderCustomBusiness;
   @Autowired
   @Lazy
   protected OrderModuleClient orderModuleClient;
   @Autowired
   @Lazy
   protected AllocStallApi allocStallApi;
   @Autowired
   @Lazy
   protected AccInfoServiceV3Api accInfoServiceV3Api;
   @Autowired
   @Lazy
   protected DeviceApi deviceApi;
   @Lazy
   @Autowired
   protected LeNumUtil numUtil;
   @Lazy
   @Autowired
   protected ReportOrderApi reportOrderApi;

   public PageVO<OrderListAndroidVO> queryPage(OrderListAndroidQueryDTO queryDTO) {
      if (LeNumUtil.isValidId(queryDTO.getNuClearMode())) {
         CustPayVO custPayInfo = this.checkCustPayInfo(queryDTO.getNuClearMode(), queryDTO.getCustId(), queryDTO.getOpenId(), queryDTO.getSerialNum(), queryDTO.getQrCode());
         queryDTO.setCustId(custPayInfo.getCustId());
      }

      OrderQueryHelper.initQueryDate(queryDTO, 0, 7);
      OrderQueryHelper.initQueryParam(queryDTO);
      PageMethod.startPage(queryDTO);
      List<OrderIdDateVO> orderIdDatePage = this.orderInfoService.queryOrderId(queryDTO.convertToOrderSearchParam(), (OrderUserPermissionDTO)null);
      List<OrderListAndroidVO> records = this.orderInfoService.listOrderForAndroid((List)orderIdDatePage.stream().map(OrderIdDateVO::getId).collect(Collectors.toList()), (List)orderIdDatePage.stream().map(OrderIdDateVO::getOrderDate).collect(Collectors.toList()));
      this.fillOrderDetail(records, false);
      PageVO<OrderListAndroidVO> pageVO = PageVO.of(orderIdDatePage, records);
      this.orderCustomBusiness.android().didQueryOrderPage(queryDTO, pageVO);
      return pageVO;
   }

   public PageVO<OrderListAndroidVO> queryPageByCust(OrderListAndroidCustQueryDTO queryDTO) {
      OrderListAndroidQueryDTO listAndroidQueryDTO = queryDTO.convertToOrderListAndroidQueryDTO();
      listAndroidQueryDTO.setOrderStateList(OrderStateEnum.validStateList());
      if (!LeNumUtil.isValidId(queryDTO.getCustId())) {
         CustPayVO custPayInfo = this.checkCustPayInfo(queryDTO.getNuClearMode(), queryDTO.getCustId(), queryDTO.getOpenId(), queryDTO.getSerialNum(), queryDTO.getQrCode());
         listAndroidQueryDTO.setCustId(custPayInfo.getCustId());
      } else {
         listAndroidQueryDTO.setCustId(queryDTO.getCustId());
      }

      return this.queryPage(listAndroidQueryDTO);
   }

   public OrderInfoAndroidVO getInfo(Long orderId) {
      OrderInfo orderInfo = this.orderInfoService.getById(orderId);
      if (orderInfo == null) {
         return null;
      } else {
         OrderInfoAndroidVO vo = OrderInfoAndroidVO.of(orderInfo);
         List<OrderDetailAndroidVO> detailAndroidVOList = this.orderDetailService.getOrderDetailList(orderId, orderInfo.getOrderDate())
                 .stream().map(OrderDetailAndroidVO::of).collect(Collectors.toList());
         this.orderDetailService.fillOrderDetailImage(detailAndroidVOList);
         vo.setOrderDetailList(detailAndroidVOList);
         this.orderDishesAndroidBusiness.fillDetailMakingPartComplete(vo.getOrderId(), vo.getDishesState(), vo.getOrderDetailList());
         OrderDelivery delivery = this.orderDeliveryService.getByOrderId(orderId, orderInfo.getOrderDate());
         if (delivery != null) {
            vo.fillDeliveryInfo(delivery);
         }

         return vo;
      }
   }

   public OrderInfoAndroidVO queryInfo(OrderInfoAndroidQueryDTO queryDTO) {
      String qrCode = queryDTO.getQrCode();
      if (CharSequenceUtil.isNotBlank(qrCode)) {
         OrdLeCodeDTO ordLeCodeDTO = LeCodeUtil.readLeCode(qrCode);
         queryDTO.setOrderId(LeCodeUtil.getPlatformId(ordLeCodeDTO));
      }

      return this.getInfo(queryDTO.getOrderId());
   }

   public ReportDeviceOrderSumVO getOrderStat(OrderStatAndroidQueryDTO queryDTO) {
      JavaxValidateUtils.validate(queryDTO);
      ReportOrderSumQueryDTO reportOrderSumQueryDTO = new ReportOrderSumQueryDTO();
      reportOrderSumQueryDTO.setMachineSn(queryDTO.getAvailableMachineSn());
      return this.reportOrderApi.reportDeviceOrderSum(reportOrderSumQueryDTO);
   }

   public PageVO<DeviceOrderDishesSumVO> pageGoodsState(DeviceOrderDishesSumQueryDTO queryDTO) {
      JavaxValidateUtils.validate(queryDTO);
      return this.reportOrderApi.reportOrderDishesSum(queryDTO);
   }

   public void fillOrderDetail(List<OrderListAndroidVO> orderInfoList, boolean filterRefundedDetails) {
      if (CollUtil.isNotEmpty(orderInfoList)) {
         List<Long> orderIds = orderInfoList.stream().map(OrderListAndroidVO::getOrderId).collect(Collectors.toList());
         List<LocalDate> orderDates = orderInfoList.stream().map(OrderListAndroidVO::getOrderDate).collect(Collectors.toList());
         Map<Long, List<OrderDetailAndroidVO>> detailGroupByOrderId = this.orderDetailService.getOrderDetailList(orderIds, orderDates).stream().filter((s) -> {
            return !filterRefundedDetails || !DetailStateEnum.ifRefunded(s.getDetailState());
         }).map(OrderDetailAndroidVO::of).collect(Collectors.groupingBy(OrderDetailAndroidVO::getOrderId));
         Iterator var6 = orderInfoList.iterator();

         while(var6.hasNext()) {
            OrderListAndroidVO orderListAndroidVO = (OrderListAndroidVO)var6.next();
            orderListAndroidVO.setOrderDetailList(detailGroupByOrderId.getOrDefault(orderListAndroidVO.getOrderId(), CollUtil.newArrayList(new OrderDetailAndroidVO[0])));
            this.orderDishesAndroidBusiness.fillDetailMakingPartComplete(orderListAndroidVO.getOrderId(), orderListAndroidVO.getDishesState(), orderListAndroidVO.getOrderDetailList());
         }

         List<OrderDetailAndroidVO> detaiVoList = orderInfoList.stream().flatMap((s) -> {
            return s.getOrderDetailList().stream();
         }).collect(Collectors.toList());
         this.orderDetailService.fillOrderDetailImage(detaiVoList);
      }

   }

   public CustPayVO checkCustPayInfo(Integer nuClearMode, Long custId, String openId, String serialNum, String qrCode) {
      CustPayVO custPayVO = null;
      if (!NuclearModeEnum.NUCLEAR_MODE_CREDIT.getKey().equals(nuClearMode) && !NuclearModeEnum.NUCLEAR_MODE_BRUSH.getKey().equals(nuClearMode)) {
         if (NuclearModeEnum.NUCLEAR_MODE_QRCODE.getKey().equals(nuClearMode) && LeCodeUtil.isLeCode(qrCode)) {
            OrdLeCodeDTO ordLeCodeDTO = LeCodeUtil.readLeCode(qrCode);
            if (ordLeCodeDTO.ifPersonalPay()) {
               custPayVO = this.orderModuleClient.custPayInfoQuery(CustPayInfoQueryParam.ofCustId(LeCodeUtil.getPlatformIdThenExpire(ordLeCodeDTO)));
            } else if (ordLeCodeDTO.ifTake()) {
               OrderInfo orderInfo = this.orderInfoService.checkAndGetOrderInfo(LeCodeUtil.getPlatformIdThenExpire(ordLeCodeDTO));
               if (LeNumUtil.isValidId(orderInfo.getCustId())) {
                  custPayVO = this.orderModuleClient.custPayInfoQuery(CustPayInfoQueryParam.ofCustId(orderInfo.getCustId()));
               }
            }
         }
      } else {
         CustPayInfoQueryParam custPayDTO = new CustPayInfoQueryParam();
         if (CharSequenceUtil.isNotBlank(serialNum)) {
            custPayDTO.setSerialNum(serialNum);
         } else if (LeNumUtil.isValidId(custId)) {
            custPayDTO.setCustId(custId);
         } else if (CharSequenceUtil.isNotBlank(openId)) {
            custPayDTO.setOpenid(openId);
         }

         custPayVO = this.orderModuleClient.custPayInfoQuery(custPayDTO);
      }

      if (custPayVO == null) {
         throw new ServiceException(I18n.getMessage("order.buffet.no-cust"));
      } else {
         return custPayVO;
      }
   }
}
