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

import com.clx.performance.dao.OrderChildDao;
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.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.VehicleWarnDelayWarnService;
import com.clx.performance.utils.LocalDateTimeUtils;
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.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class VehicleWarnDelayWarnServiceImpl implements VehicleWarnDelayWarnService {
    // 装卸车默认时间(min)
    private static final Integer LOAD_UNLOAD_TIME_DEFAULT = 60;
    // 最近30天装卸车时间
    private static final int LOAD_UNLOAD_DAY = 30;

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

    /**
     * 运单延误
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delayTimeout(OrderChild orderChild, VehicleWarnChild vehicleWarnChild,
                             VehicleWarnCommonInfoDTO commonInfo){
        if (vehicleWarnChild.getArriveReceiveExpectTime() == null) {return;}

        // 拉运结束时间
        LocalDateTime transportEndTime = commonInfo.getTransportEndTime();

        // 预警到达货源地时间
        Integer sendAddressTime = commonInfo.getSendAddressTime();
        // 装车时间
        Integer loadTime = getLoadTime(orderChild.getSendAddressId(), orderChild.getReceiveAddressId(),
                orderChild.getSendSystemAddressId(), orderChild.getReceiveSystemAddressId(),
                commonInfo.getCurrentTime());
        // 到目的地时间
        Integer expectTime = vehicleWarnChild.getArriveReceiveExpectTime();
        // 卸车时间
        Integer unloadTime = getUnloadTime(orderChild.getSendAddressId(), orderChild.getReceiveAddressId(),
                orderChild.getSendSystemAddressId(), orderChild.getReceiveSystemAddressId(),
                commonInfo.getCurrentTime());

        // 计算需要的时间
        Integer needTime = sendAddressTime + loadTime + expectTime + unloadTime;

        // 超时
        if (transportEndTime.isAfter(LocalDateTime.now().plusMinutes(needTime))){return;}

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

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

    }

    private void doDelayTimeout(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);

    }

    /**
     * 获取装车平均时间（min）
     */
    private Integer getLoadTime(Integer sendAddressId, Integer receiveAddressId,
                             Integer sendSystemAddressId, Integer receiveSystemAddressId,
                             LocalDateTime now){
        Integer time = orderChildDao.loadTimeAvg(sendAddressId, receiveAddressId, sendSystemAddressId,
                receiveSystemAddressId, LocalDateTimeUtils.formatTime(now.minusDays(LOAD_UNLOAD_DAY)));
        if (time == null) {return LOAD_UNLOAD_TIME_DEFAULT;}
        return time/60;
    }

    /**
     * 获取卸车平均时间（min）
     */
    private Integer getUnloadTime(Integer sendAddressId, Integer receiveAddressId,
                             Integer sendSystemAddressId, Integer receiveSystemAddressId,
                             LocalDateTime now){
        Integer time = orderChildDao.unloadTimeAvg(sendAddressId, receiveAddressId, sendSystemAddressId,
                receiveSystemAddressId, LocalDateTimeUtils.formatTime(now.minusDays(LOAD_UNLOAD_DAY)));
        if (time == null) {return LOAD_UNLOAD_TIME_DEFAULT;}
        return time/60;
    }

}
