package com.clx.performance.service.impl.vehiclewarn;

import com.clx.performance.dao.vehiclewarn.VehicleWarnConfigDao;
import com.clx.performance.dao.vehiclewarn.VehicleWarnInfoDao;
import com.clx.performance.dto.vehiclewarn.VehicleWarnCommonInfoDTO;
import com.clx.performance.enums.OrderChildEnum;
import com.clx.performance.enums.vehiclewarn.VehicleWarnConfigEnum;
import com.clx.performance.enums.vehiclewarn.VehicleWarnInfoEnum;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.vehiclewarn.VehicleWarnChild;
import com.clx.performance.model.vehiclewarn.VehicleWarnConfig;
import com.clx.performance.model.vehiclewarn.VehicleWarnInfo;
import com.clx.performance.service.vehiclewarn.VehicleWarnCommonService;
import com.clx.performance.service.vehiclewarn.VehicleWarnReceiveAddressWarnService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class VehicleWarnReceiveAddressWarnServiceImpl implements VehicleWarnReceiveAddressWarnService {
    private static final Integer DISTANCE_DEFAULT = 2000;

    @Autowired
    private VehicleWarnConfigDao vehicleWarnConfigDao;
    @Autowired
    private VehicleWarnInfoDao vehicleWarnInfoDao;
    @Autowired
    private VehicleWarnCommonService vehicleWarnCommonService;

    /**
     * 前往目的地超时
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void gotoReceiveAddressTimeout(OrderChild orderChild, VehicleWarnChild vehicleWarnChild, VehicleWarnCommonInfoDTO commonInfo){
        if (vehicleWarnChild.getArriveReceiveExpectTime() == null) {return;}

        // 未装车前往目的地判断
        if (Objects.equals(orderChild.getStatus(), OrderChildEnum.Status.ARRIVE_SEND.getCode())){

            // 首次不处理预警
            if (vehicleWarnChild.getReceiveAddressDistance() == null){
                return;
            }
            else {
                Integer needDistance = commonInfo.getReceiveAddressDistance();

                // 未前往目的地不处理预警
                if (vehicleWarnChild.getReceiveAddressDistance()-needDistance < DISTANCE_DEFAULT){return;}

                // 假定当前已装车
                orderChild.setLoadTime(LocalDateTime.now());
            }
        }

        // 理论时间
        Integer expectTime = vehicleWarnChild.getArriveReceiveExpectTime();

        // 计算需要的时间
        Integer needTime = commonInfo.getReceiveAddressTime();

        List<VehicleWarnConfig> vehicleWarnConfigList = vehicleWarnConfigDao.listByWarnType(VehicleWarnConfigEnum.WarnType.GOTO_RECEIVE_TIMEOUT.getCode());
        if (vehicleWarnConfigList.isEmpty()) {return;}

        for (VehicleWarnConfig item : vehicleWarnConfigList) {
            doGotoReceiveAddressTimeout(orderChild, vehicleWarnChild, item, expectTime, needTime);
        }

    }

    private void doGotoReceiveAddressTimeout(OrderChild orderChild, VehicleWarnChild vehicleWarnChild, VehicleWarnConfig vehicleWarnConfig, Integer expectTime, Integer needTime){
        VehicleWarnInfo vehicleWarnInfo = vehicleWarnInfoDao.findByChildNoAndWarnConfigId(vehicleWarnChild.getChildNo(), vehicleWarnConfig.getId()).orNull();
        if (vehicleWarnInfo != null && Objects.equals(vehicleWarnInfo.getStatus(), VehicleWarnInfoEnum.Status.RESOLVE.getCode())){
            return;
        }

        // 暂停检测
        boolean suspend = vehicleWarnCommonService.suspendCheck(vehicleWarnChild, vehicleWarnConfig.getId());
        if (suspend) {return;}

        LocalDateTime loadTime = orderChild.getLoadTime();

        // 超时判断
        int time = vehicleWarnConfig.getTimeoutRatio().multiply(new BigDecimal(expectTime)).divide(new BigDecimal("100"), 0, RoundingMode.HALF_UP).intValue();
        if (loadTime.plusMinutes(expectTime).plusMinutes(time).isAfter(LocalDateTime.now().plusMinutes(needTime))){return;}

        // 更新
        vehicleWarnCommonService.vehicleWarnInfoUpdate(orderChild, vehicleWarnInfo, vehicleWarnConfig);
    }

    /**
     * 到达目的地超时
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void arriveReceiveAddressTimeout(OrderChild orderChild, VehicleWarnChild vehicleWarnChild, VehicleWarnCommonInfoDTO commonInfo){
        if (vehicleWarnChild.getArriveReceiveExpectTime() == null) {return;}

        // 未装车前往目的地判断
        if (Objects.equals(orderChild.getStatus(), OrderChildEnum.Status.ARRIVE_SEND.getCode())){

            // 首次不处理预警
            if (vehicleWarnChild.getReceiveAddressDistance() == null){
                return;
            }
            else {
                Integer needDistance = commonInfo.getReceiveAddressDistance();

                // 未前往目的地不处理预警
                if (vehicleWarnChild.getReceiveAddressDistance()-needDistance < DISTANCE_DEFAULT){return;}
            }
        }

        // 计算需要的时间
        int needTime = commonInfo.getReceiveAddressTime();
        LocalDateTime lastArriveReceiveTime = commonInfo.getLastArriveReceiveTime();

        // 超时判断
        LocalDateTime now = commonInfo.getCurrentTime();
        log.info("到达目的地超时, childNo:{}, needTime:{}", orderChild.getChildNo(), needTime);

        if (lastArriveReceiveTime.isAfter(now.plusMinutes(needTime))) {return;}

        List<VehicleWarnConfig> vehicleWarnConfigList = vehicleWarnConfigDao.listByWarnType(VehicleWarnConfigEnum.WarnType.ARRIVE_RECEIVE_DELAY.getCode());
        if (vehicleWarnConfigList.isEmpty()) {return;}

        for (VehicleWarnConfig item : vehicleWarnConfigList) {
            doArriveReceiveAddressTimeout(orderChild, vehicleWarnChild, item);
        }

    }

    private void doArriveReceiveAddressTimeout(OrderChild orderChild, VehicleWarnChild vehicleWarnChild, VehicleWarnConfig vehicleWarnConfig){
        VehicleWarnInfo vehicleWarnInfo = vehicleWarnInfoDao.findByChildNoAndWarnConfigId(vehicleWarnChild.getChildNo(), vehicleWarnConfig.getId()).orNull();
        if (vehicleWarnInfo != null && Objects.equals(vehicleWarnInfo.getStatus(), VehicleWarnInfoEnum.Status.RESOLVE.getCode())){
            return;
        }

        // 暂停检测
        boolean suspend = vehicleWarnCommonService.suspendCheck(vehicleWarnChild, vehicleWarnConfig.getId());
        if (suspend) {return;}

        // 更新
        vehicleWarnCommonService.vehicleWarnInfoUpdate(orderChild, vehicleWarnInfo, vehicleWarnConfig);
    }

}
