package com.bonus.canteen.core.order.deprecated.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.canteen.core.auth.api.MgrAuthApi;
import com.bonus.canteen.core.auth.po.MgrUserAuthPO;
import com.bonus.canteen.core.common.utils.LogUtil;
import com.bonus.canteen.core.customer.vo.CustPlaceListDutyAreaVO;
import com.bonus.canteen.core.order.client.OrderModuleClient;
import com.bonus.canteen.core.order.client.po.CustPlaceListQueryParam;
import com.bonus.canteen.core.order.common.constants.OrderStateEnum;
import com.bonus.canteen.core.order.common.model.OrderDetail;
import com.bonus.canteen.core.order.common.service.OrderDetailService;
import com.bonus.canteen.core.order.common.vo.OrderDetailVO;
import com.bonus.canteen.core.order.deprecated.dto.MacMarketNotWriteOffDTO;
import com.bonus.canteen.core.order.deprecated.dto.MacMarketOrdDTO;
import com.bonus.canteen.core.order.deprecated.dto.MacOrdRefundQueryDTO;
import com.bonus.canteen.core.order.deprecated.mapper.OrdAppInfoMapper;
import com.bonus.canteen.core.order.deprecated.mapper.OrdDetailMapper;
import com.bonus.canteen.core.order.deprecated.model.OrdAppInfo;
import com.bonus.canteen.core.order.deprecated.param.MacOrdParam;
import com.bonus.canteen.core.order.deprecated.param.OrdMachineParam;
import com.bonus.canteen.core.order.deprecated.param.OrdParam;
import com.bonus.canteen.core.order.deprecated.service.OrdAppInfoService;
import com.bonus.canteen.core.order.deprecated.vo.*;
import com.bonus.canteen.core.order.utils.LeOrderUtil;
import com.bonus.canteen.core.order.weight.dto.QueryWeighBindDetailDTO;
import com.bonus.canteen.core.pay.common.constants.PayStateEnum;
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 javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class OrdAppInfoServiceImpl extends ServiceImpl<OrdAppInfoMapper, OrdAppInfo> implements OrdAppInfoService {
   private static final Logger log = LoggerFactory.getLogger(OrdAppInfoServiceImpl.class);
   @Resource
   private OrdDetailMapper ordDetailMapper;
   @Autowired
   @Lazy
   private OrderDetailService orderDetailService;
   @Autowired
   private MgrAuthApi mgrAuthApi;
   @Autowired
   private OrderModuleClient orderModuleClient;

   public List<AppDtlOrdDetailVO> getAppDtlOrdDetail(String openId, String macOrdId, QueryWeighBindDetailDTO param) {
      return this.ordDetailMapper.getAppDtlOrdDetail(openId, macOrdId, param);
   }

   public List<OrdAssignSrcMacVO> getOrderListForAndroid(MacOrdParam macOrdParam) {
      LogUtil.info("getOrderListForAndroid ", macOrdParam);
      return ((OrdAppInfoMapper)this.baseMapper).getOrderListForAndroid(macOrdParam);
   }

   public List<OrdAssignSrcMacVO> getOrderShopListForAndroid(MacOrdParam macOrdParam) {
      LogUtil.info("getOrderShopListForAndroid ", macOrdParam);
      return ((OrdAppInfoMapper)this.baseMapper).getOrderShopListForAndroid(macOrdParam);
   }

   public OrdCurrentReserveMacVO getReserveOrderListForAndroid(MacOrdParam macOrdParam) {
      LogUtil.info("getReserveOrderListForAndroid ", macOrdParam);
      return ((OrdAppInfoMapper)this.baseMapper).getReserveOrderListForAndroid(macOrdParam);
   }

   public List<OrdAssignSrcMacOldVO> queryOrdListBySn(MacOrdRefundQueryDTO ordRefundQueryDTO) {
      LogUtil.info("queryOrdListBySn ", ordRefundQueryDTO);
      return ((OrdAppInfoMapper)this.baseMapper).queryOrdListBySn(ordRefundQueryDTO, LocalDate.now(), PayStateEnum.PAY_SUCC.getKey());
   }

   public Page<OrdInfoVO> queryPageOrdInfoDetail(Page<?> page, OrdParam ordParam) {
      MgrUserAuthPO authPO = this.mgrAuthApi.getUserAuthPO();
      if (ordParam.getOrdTimeMin() == null) {
         ordParam.setOrdDateMin((LocalDate)LeOrderUtil.queryDateRange().get(0));
      }

      if (ordParam.getOrdTimeMax() == null) {
         ordParam.setOrdDateMax((LocalDate)LeOrderUtil.queryDateRange().get(1));
      }

      LogUtil.info("queryPageOrdInfoDetail", ordParam, authPO);
      return ((OrdAppInfoMapper)this.baseMapper).queryPageOrdInfoDetail(page, ordParam, authPO);
   }

   public Page<OrdInfoVO> queryPageOrdInfoMachine(Page<OrdInfoVO> pageParam, OrdMachineParam ordMachineParam) {
      LogUtil.info("queryPageOrdInfoMachine ", ordMachineParam);
      return ((OrdAppInfoMapper)this.baseMapper).queryPageOrdInfoMachine(pageParam, ordMachineParam);
   }

   public Page<MacMarketOrdInfoVO> pageMacOrdInfoDetailByConditon(MacMarketOrdDTO marketOrdDTO) {
      Page page = new Page(marketOrdDTO.getCurrent(), marketOrdDTO.getSize());
      if (marketOrdDTO.getStartDate() == null) {
         marketOrdDTO.setStartDate((LocalDate)LeOrderUtil.queryDateRange().get(0));
      }

      if (marketOrdDTO.getEndDate() == null) {
         marketOrdDTO.setEndDate((LocalDate)LeOrderUtil.queryDateRange().get(1));
      }

      LogUtil.info("pageMacOrdInfoDetailByConditon", marketOrdDTO);
      Page<MacMarketOrdInfoVO> voPage = ((OrdAppInfoMapper)this.baseMapper).macOrdInfoDetailByConditon(page, marketOrdDTO);
      List<MacMarketOrdInfoVO> records = voPage.getRecords();
      if (CollectionUtil.isEmpty(records)) {
         return voPage;
      } else {
         List<Long> orderIds = records.stream().map(MacMarketOrdInfoVO::getOrdId).collect(Collectors.toList());
         List<LocalDate> orderDates = records.stream().map(MacMarketOrdInfoVO::getOrdGoodsDate).collect(Collectors.toList());
         Map<Long, List<OrderDetail>> detailGroup = this.orderDetailService.getOrderDetailList(orderIds, orderDates).stream().collect(Collectors.groupingBy(OrderDetail::getOrderId));
         records.forEach((info) -> {
            info.setOrdDetailList((detailGroup.getOrDefault(info.getOrdId(), ListUtil.empty())).stream().map(OrdDetailMachineVO::of).collect(Collectors.toList()));
         });
         return voPage;
      }
   }

   public Page<MacMarketOrdInfoVO> pageMacOrdInfoNotWriteOff(MacMarketNotWriteOffDTO marketOrdDTO) {
      Page page = new Page(marketOrdDTO.getCurrent(), marketOrdDTO.getSize());
      LogUtil.info("pageMacOrdInfoNotWriteOff", marketOrdDTO);
      Page<MacMarketOrdInfoVO> voPage = ((OrdAppInfoMapper)this.baseMapper).pageMacOrdInfoNotWriteOff(page, marketOrdDTO);
      List<MacMarketOrdInfoVO> records = voPage.getRecords();
      if (CollectionUtil.isEmpty(records)) {
         return voPage;
      } else {
         List<Long> ordIds = records.stream().map(MacMarketOrdInfoVO::getOrdId).collect(Collectors.toList());
         List<LocalDate> ordDates = records.stream().map(MacMarketOrdInfoVO::getOrdGoodsDate).collect(Collectors.toList());
         Map<Long, List<OrderDetailVO>> detailVoMap = this.orderDetailService.getDetailVOGroupByOrderIdList(ordIds, ordDates, false);
         records.forEach((info) -> {
            List<OrderDetailVO> detailList = detailVoMap.getOrDefault(info.getOrdId(), ListUtil.empty());
            AtomicReference<Integer> goodsCount = new AtomicReference(0);
            List<OrdDetailMachineVO> collect = detailList.stream().map((detail) -> {
               OrdDetailMachineVO detailMachineVO = new OrdDetailMachineVO();
               detailMachineVO.setDetailId(detail.getDetailId());
               detailMachineVO.setGoodsName(detail.getGoodsDishesName());
               detailMachineVO.setPrice(detail.getPrice().intValue());
               detailMachineVO.setUnit(detail.getSalesMode().toString());
               detailMachineVO.setGoodsGetNum(detail.getGoodsGetNum());
               detailMachineVO.setGoodsSubNum(detail.getQuantity());
               detailMachineVO.setQuantity(detail.getQuantity());
               detailMachineVO.setRealAmount(detail.getRealAmount().intValue());
               detailMachineVO.setOrdState(detail.getDetailState());
               goodsCount.updateAndGet((v) -> {
                  return v + detail.getQuantity();
               });
               return detailMachineVO;
            }).collect(Collectors.toList());
            info.setGoodsCount((Integer)goodsCount.get());
            info.setOrdDetailList(collect);
         });
         return voPage;
      }
   }
}
