package com.bonus.canteen.core.kitchen.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.bonus.canteen.core.allocation.api.AllocCanteenApi;
import com.bonus.canteen.core.allocation.canteen.model.AllocCanteen;
import com.bonus.canteen.core.device.api.DeviceApi;
import com.bonus.canteen.core.device.manage.controller.deprecated.dto.MacApiUSelectDto;
import com.bonus.canteen.core.device.manage.controller.deprecated.vo.MacMachineApiVO;
import com.bonus.canteen.core.device.manage.service.DeviceInfoService;
import com.bonus.canteen.core.kitchen.entity.dto.PassengerFlowByTimeDTO;
import com.bonus.canteen.core.kitchen.entity.dto.PassengerFlowQueryDTO;
import com.bonus.canteen.core.kitchen.entity.vo.DeviceQueryPresentNumVo;
import com.bonus.canteen.core.kitchen.entity.vo.PassengerFlowVO;
import com.bonus.canteen.core.kitchen.entity.vo.PresentFlowNowDayVO;
import com.bonus.canteen.core.kitchen.entity.vo.PresentFlowVO;
import com.bonus.canteen.core.kitchen.mapper.DevicePassengerFlowMapper;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.houqin.constant.SourceTypeEnum;
import lombok.Generated;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Primary
@Component
public class DevicePassengerFlowService {
   @Generated
   private static final Logger log = LoggerFactory.getLogger(DevicePassengerFlowService.class);
   private static final String PASSENGER_FLOW_MESSAGE_TOPIC = "back-device-passenger-flow-{}";
   @Autowired
   @Lazy
   private DeviceApi deviceApi;
   @Autowired
   @Lazy
   private DevicePassengerFlowMapper devicePassengerFlowMapper;
   @Lazy
   @Autowired
   private AllocCanteenApi allocCanteenApi;
   @Lazy
   @Autowired
   private DeviceInfoService deviceInfoService;

   public PassengerFlowVO queryPassengerNum(PassengerFlowQueryDTO content) {
      MacApiUSelectDto macApiUSelectDto = (MacApiUSelectDto) BeanUtil.copyProperties(content, MacApiUSelectDto.class, new String[0]);
      macApiUSelectDto.setMchType(SourceTypeEnum.PERSON_FLOW_DETECTOR.getKey());
      List<MacMachineApiVO> machineList = this.deviceApi.getMachineList(macApiUSelectDto);
      if (machineList.isEmpty()) {
         throw new ServiceException("当前食堂无客流统计设备");
      } else {
         PassengerFlowVO passengerFlowVO = this.devicePassengerFlowMapper.queryPresentCount(LocalDate.now(), content.getCanteenId());
         if (Objects.isNull(passengerFlowVO)) {
            passengerFlowVO = new PassengerFlowVO();
         }

         List<PresentFlowVO> presentFlowVOList = new ArrayList();
         Iterator var6 = content.getPresentDate().iterator();

         while(var6.hasNext()) {
            LocalDate localDate = (LocalDate)var6.next();
            List<PassengerFlowByTimeDTO> flowByTime = this.devicePassengerFlowMapper.queryPassengerFlowByTime(localDate, content.getPeriods(), content.getCanteenId());
            List<Long> enterList = this.createPassengerFlowList(content.getPeriods(), localDate);
            List<Long> exitsList = this.createPassengerFlowList(content.getPeriods(), localDate);
            List<Long> presentList = this.createPassengerFlowList(content.getPeriods(), localDate);
            this.processData(flowByTime, enterList, exitsList, presentList);
            long maxPresent = (Long)presentList.stream().max(Long::compareTo).orElse(0L);
            PresentFlowVO presentFlowVO = new PresentFlowVO();
            presentFlowVO.setPresentList(presentList);
            presentFlowVO.setExitList(exitsList);
            presentFlowVO.setEnterList(enterList);
            presentFlowVO.setDate(localDate);
            presentFlowVO.setPeakNum(maxPresent);
            presentFlowVOList.add(presentFlowVO);
         }

         passengerFlowVO.setPresentFlowVOList(presentFlowVOList);
         AllocCanteen allocCanteen = this.allocCanteenApi.getAllocCanteen(content.getCanteenId());
         passengerFlowVO.setCapacity(allocCanteen.getCapacity());
         passengerFlowVO.setUpdateTime(LocalDateTime.now());
         return passengerFlowVO;
      }
   }

   public List<PresentFlowNowDayVO> queryAllAllocCanteenPresentFlow() {
      List<PresentFlowNowDayVO> flowList = new ArrayList();
      List<DeviceQueryPresentNumVo> list = this.devicePassengerFlowMapper.queryPresentNumByCanteenId(LocalDate.now());
      if (CollUtil.isEmpty(list)) {
         return new ArrayList<>();
      } else {
         Map<Long, Integer> collect = (Map)list.stream().collect(Collectors.toMap(DeviceQueryPresentNumVo::getCanteenId, DeviceQueryPresentNumVo::getPresentNum));
         List<AllocCanteen> allocCanteens = this.allocCanteenApi.listAllCanteen((Boolean)null);
         Iterator var5 = allocCanteens.iterator();

         while(var5.hasNext()) {
            AllocCanteen allocCanteen = (AllocCanteen)var5.next();
            boolean ifExit = collect.containsKey(allocCanteen.getCanteenId());
            if (ifExit) {
               Integer presentNum = (Integer)collect.get(allocCanteen.getCanteenId());
               PresentFlowNowDayVO presentFlowNowDayVO = new PresentFlowNowDayVO();
               presentFlowNowDayVO.setPresentNum(presentNum);
               presentFlowNowDayVO.setCanteenName(allocCanteen.getCanteenName());
               presentFlowNowDayVO.setBusinessState(allocCanteen.getBusinessState());
               presentFlowNowDayVO.setCanteenId(allocCanteen.getCanteenId());
               presentFlowNowDayVO.setCapacity(allocCanteen.getCapacity());
               presentFlowNowDayVO.setImgUrl(allocCanteen.getImgUrl());
               presentFlowNowDayVO.setStartBusinessTime(allocCanteen.getStartBusinessTime());
               presentFlowNowDayVO.setEndBusinessTime(allocCanteen.getEndBusinessTime());
               flowList.add(presentFlowNowDayVO);
            }
         }

         return flowList;
      }
   }

   private List<Long> createPassengerFlowList(Integer periods, LocalDate date) {
      int size = periods * 24;
      if (date.isEqual(LocalDate.now())) {
         LocalDateTime nowTime = LocalDateTime.now();
         int hour = nowTime.getHour();
         int minute = nowTime.getMinute();
         size = periods * hour + (minute == 0 ? minute + 1 : minute) * periods / 60 + 1;
      }

      Long[] arrayInt = new Long[size];
      Arrays.fill(arrayInt, 0L);
      List<Long> presentNumberList = Arrays.asList(arrayInt);
      return presentNumberList;
   }

   private void processData(List<PassengerFlowByTimeDTO> flowByTime, List<Long> enterList, List<Long> exitsList, List<Long> passengerFlowList) {
      if (!CollUtil.isEmpty(flowByTime)) {
         boolean hasPassengerFlow = CollUtil.isNotEmpty(passengerFlowList);
         boolean hasEnterList = CollUtil.isNotEmpty(enterList);
         boolean hasExitList = CollUtil.isNotEmpty(exitsList);
         Iterator var8 = flowByTime.iterator();

         while(true) {
            int timeNum;
            do {
               if (!var8.hasNext()) {
                  return;
               }

               PassengerFlowByTimeDTO dto = (PassengerFlowByTimeDTO)var8.next();
               timeNum = dto.getTimeNum();
               if (hasPassengerFlow) {
                  passengerFlowList.set(timeNum, (Long)passengerFlowList.get(timeNum) + (long)dto.getFlowNum());
               }

               if (hasEnterList) {
                  enterList.set(timeNum, (Long)enterList.get(timeNum) + (long)dto.getEnterNum());
               }

               if (hasExitList) {
                  exitsList.set(timeNum, (Long)exitsList.get(timeNum) + (long)dto.getExitNum());
               }
            } while(timeNum >= passengerFlowList.size() - 1);

            long presentNum = hasPassengerFlow ? (Long)passengerFlowList.get(timeNum) : 0L;
            long enterNum = hasEnterList ? (Long)enterList.get(timeNum) : 0L;
            long exitNum = hasExitList ? (Long)exitsList.get(timeNum) : 0L;

            for(int i = timeNum + 1; i < passengerFlowList.size(); ++i) {
               if (hasPassengerFlow) {
                  passengerFlowList.set(i, presentNum);
               }

               if (hasEnterList) {
                  enterList.set(i, enterNum);
               }

               if (hasExitList) {
                  exitsList.set(i, exitNum);
               }
            }
         }
      }
   }
}
