package com.hotwj.platform.workbench.strategy.impl;

import com.hotwj.platform.config.vehicleSecondaryMaintenanceConfig.domain.bo.HotVehicleSecondaryMaintenanceConfigBo;
import com.hotwj.platform.config.vehicleSecondaryMaintenanceConfig.domain.vo.HotVehicleSecondaryMaintenanceConfigVo;
import com.hotwj.platform.config.vehicleSecondaryMaintenanceConfig.service.IHotVehicleSecondaryMaintenanceConfigService;
import com.hotwj.platform.resourceManagement.vehicleMaintenance.domain.vo.HotVehicleMaintenanceVo;
import com.hotwj.platform.resourceManagement.vehicleMaintenance.service.IHotVehicleMaintenanceService;
import com.hotwj.platform.resourceManagement.vehicleManagement.utils.VehicleUtils;
import com.hotwj.platform.workbench.domain.enums.GovHiddenDangerType;
import com.hotwj.platform.workbench.domain.vo.GovHiddenDangerDetailVo;
import com.hotwj.platform.workbench.domain.vo.VehicleRiskCalcVo;
import com.hotwj.platform.workbench.mapper.GovWorkbenchMapper;
import com.hotwj.platform.workbench.strategy.IGovRiskHandler;
import lombok.RequiredArgsConstructor;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 车辆二级维护隐患处理器
 */
@Component
@RequiredArgsConstructor
public class VehicleMaintenanceRiskHandler implements IGovRiskHandler {

    private final GovWorkbenchMapper govWorkbenchMapper;
    private final IHotVehicleSecondaryMaintenanceConfigService hotVehicleSecondaryMaintenanceConfigService;
    private final IHotVehicleMaintenanceService hotVehicleMaintenanceService;

    @Override
    public String getType() {
        return GovHiddenDangerType.VEHICLE_MAINTENANCE.getKey();
    }

    @Override
    public long count(String districtCode, Long companyId) {
        return getRisks(districtCode, companyId).size();
    }

    @Override
    public TableDataInfo<GovHiddenDangerDetailVo> list(String districtCode, Long companyId, PageQuery pageQuery) {
        List<GovHiddenDangerDetailVo> risks = getRisks(districtCode, companyId);

        // 内存分页
        int total = risks.size();
        Integer pageNum = pageQuery.getPageNum();
        Integer pageSize = pageQuery.getPageSize();

        if (pageNum == null) pageNum = 1;
        if (pageSize == null) pageSize = 10;

        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, total);

        if (start >= total) {
            TableDataInfo<GovHiddenDangerDetailVo> empty = TableDataInfo.build(new ArrayList<>());
            empty.setTotal(total);
            return empty;
        }

        List<GovHiddenDangerDetailVo> pageList = risks.subList(start, end);
        TableDataInfo<GovHiddenDangerDetailVo> tableDataInfo = TableDataInfo.build(pageList);
        tableDataInfo.setTotal(total);
        return tableDataInfo;
    }

    public Map<Long, Integer> countByCompany(String districtCode) {
        Map<Long, Integer> result = new HashMap<>();
        // 处理 districtCode 为 null 的情况，转为空字符串以匹配所有
        String code = districtCode == null ? "" : districtCode;

        // 1. 获取辖区内所有活跃车辆
        List<VehicleRiskCalcVo> vehicles = govWorkbenchMapper.selectVehicleForRiskCalc(code, null);
        if (vehicles.isEmpty()) {
            return result;
        }

        // 2. 按企业分组
        Map<Long, List<VehicleRiskCalcVo>> companyVehicles = vehicles.stream()
                .collect(Collectors.groupingBy(VehicleRiskCalcVo::getCompanyId));

        // 3. 遍历企业处理
        for (Map.Entry<Long, List<VehicleRiskCalcVo>> entry : companyVehicles.entrySet()) {
            Long companyId = entry.getKey();
            List<VehicleRiskCalcVo> cvs = entry.getValue();
            int riskCount = 0;

            // 3.1 获取该企业的二级维护配置
            try {
                HotVehicleSecondaryMaintenanceConfigBo configBo = new HotVehicleSecondaryMaintenanceConfigBo();
                configBo.setCompanyId(companyId);
                List<HotVehicleSecondaryMaintenanceConfigVo> allConfigs = hotVehicleSecondaryMaintenanceConfigService.queryList(configBo);

                List<VehicleUtils.AnnualInspectionRule> rules = allConfigs == null ? new ArrayList<>() : allConfigs.stream()
                        .filter(c -> c != null && (c.getIsEnabled() == null || c.getIsEnabled() == 1L))
                        .filter(c -> c.getIntervalYears() != null && c.getInspectionTimes() != null)
                        .sorted(Comparator.comparing(c -> c.getIntervalYears() == null ? Long.MAX_VALUE : c.getIntervalYears()))
                        .map(c -> new VehicleUtils.AnnualInspectionRule(c.getIntervalYears().intValue(), c.getInspectionTimes().intValue()))
                        .collect(Collectors.toList());

                if (rules.isEmpty()) continue;

                // 3.2 遍历车辆
                for (VehicleRiskCalcVo v : cvs) {
                    if (v.getIssueDate() == null) continue;

                    LocalDate issueDate = v.getIssueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

                    // 获取最近一次二级维护日期
                    HotVehicleMaintenanceVo lastMaintenance = hotVehicleMaintenanceService.queryLatestByVehicleId(v.getId());
                    LocalDate lastMaintenanceDate = null;
                    if (lastMaintenance != null) {
                        Date t = lastMaintenance.getFinishTime() != null ? lastMaintenance.getFinishTime() : lastMaintenance.getMaintainDate();
                        if (t != null) {
                            lastMaintenanceDate = t.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        }
                    }

                    VehicleUtils.InspectionResult calc = VehicleUtils.calculateMaintenanceStatus(rules, issueDate, lastMaintenanceDate);
                    if (calc != null && calc.getOverdueDays() > 0) {
                        riskCount++;
                    }
                }
                
                if (riskCount > 0) {
                    result.put(companyId, riskCount);
                }

            } catch (Exception e) {
                // 忽略异常，继续处理下一个企业
                e.printStackTrace();
            }
        }

        return result;
    }

    private List<GovHiddenDangerDetailVo> getRisks(String districtCode, Long targetCompanyId) {
        List<GovHiddenDangerDetailVo> result = new ArrayList<>();

        // 1. 获取辖区内所有活跃车辆
        List<VehicleRiskCalcVo> vehicles = govWorkbenchMapper.selectVehicleForRiskCalc(districtCode, targetCompanyId);
        if (vehicles.isEmpty()) {
            return result;
        }

        // 2. 按企业分组
        Map<Long, List<VehicleRiskCalcVo>> companyVehicles = vehicles.stream()
                .collect(Collectors.groupingBy(VehicleRiskCalcVo::getCompanyId));

        // 3. 遍历企业处理
        for (Map.Entry<Long, List<VehicleRiskCalcVo>> entry : companyVehicles.entrySet()) {
            Long companyId = entry.getKey();
            if (targetCompanyId != null && !targetCompanyId.equals(companyId)) {
                continue;
            }
            List<VehicleRiskCalcVo> cvs = entry.getValue();

            // 3.1 获取该企业的二级维护配置
            try {
                HotVehicleSecondaryMaintenanceConfigBo configBo = new HotVehicleSecondaryMaintenanceConfigBo();
                configBo.setCompanyId(companyId);
                List<HotVehicleSecondaryMaintenanceConfigVo> allConfigs = hotVehicleSecondaryMaintenanceConfigService.queryList(configBo);

                List<VehicleUtils.AnnualInspectionRule> rules = allConfigs == null ? new ArrayList<>() : allConfigs.stream()
                        .filter(c -> c != null && (c.getIsEnabled() == null || c.getIsEnabled() == 1L))
                        .filter(c -> c.getIntervalYears() != null && c.getInspectionTimes() != null)
                        .sorted(Comparator.comparing(c -> c.getIntervalYears() == null ? Long.MAX_VALUE : c.getIntervalYears()))
                        .map(c -> new VehicleUtils.AnnualInspectionRule(c.getIntervalYears().intValue(), c.getInspectionTimes().intValue()))
                        .collect(Collectors.toList());

                if (rules.isEmpty()) continue;

                // 3.2 遍历车辆
                for (VehicleRiskCalcVo v : cvs) {
                    if (v.getIssueDate() == null) continue;

                    LocalDate issueDate = v.getIssueDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

                    // 获取最近一次二级维护日期
                    HotVehicleMaintenanceVo lastMaintenance = hotVehicleMaintenanceService.queryLatestByVehicleId(v.getId());
                    LocalDate lastMaintenanceDate = null;
                    if (lastMaintenance != null) {
                        Date t = lastMaintenance.getFinishTime() != null ? lastMaintenance.getFinishTime() : lastMaintenance.getMaintainDate();
                        if (t != null) {
                            lastMaintenanceDate = t.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        }
                    }

                    VehicleUtils.InspectionResult calc = VehicleUtils.calculateMaintenanceStatus(rules, issueDate, lastMaintenanceDate);
                    if (calc != null && calc.getOverdueDays() > 0) {
                        GovHiddenDangerDetailVo vo = new GovHiddenDangerDetailVo();
                        vo.setId(v.getId());
                        vo.setTitle("二级维护：（" + v.getPlateNumber() + "） 已到期（" + calc.getOverdueDays() + "）天");
                        vo.setSubTitle(null);
                        
                        vo.setStatus("expired");
                        if (calc.getNextInspectionDate() != null) {
                            vo.setDeadline(Date.from(calc.getNextInspectionDate().atStartOfDay(ZoneId.systemDefault()).toInstant()));
                        }
                        vo.setRelatedId(v.getCompanyName());
                        result.add(vo);
                    }
                }

            } catch (Exception e) {
                // 忽略异常，继续处理下一个企业
                e.printStackTrace();
            }
        }

        return result;
    }
}
