package com.ruoyi.system.config;

import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 自动生成数据表
 */
@Configuration
@EnableScheduling
@Slf4j
public class TableScheduleConfig {

    private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Autowired
    private EpsInitialTrafficDataService epsInitialTrafficDataService;
    @Autowired
    private IInitialSwitchInfoDetailsService initialSwitchInfoDetailsService;
    @Autowired
    private IEpsNodeBandwidthService epsNodeBandwidthService;
    @Autowired
    private IAllInterfaceNameService allInterfaceNameService;
    @Autowired
    private IEpsServerRevenueConfigService epsServerRevenueConfigService;
    @Autowired
    private IRmEpsTopologyManagementService rmEpsTopologyManagementService;
    @Autowired
    private IEpsMethodChangeRecordService epsMethodChangeRecordService;

    // 每月25号创建下月表
    @Scheduled(cron = "0 0 0 25 * ?")
//    @Scheduled(initialDelay = 5000, fixedDelay = Long.MAX_VALUE)
    public void createNextMonthTables() {
        epsInitialTrafficDataService.createNextMonthTables();
    }

    // 每天0点执行 计算95带宽值/日
    @Scheduled(cron = "0 4 0 * * ?", zone = "Asia/Shanghai")
    public void calculate95BandwidthDaily() {
        // 获取昨天的日期范围（北京时间）
        LocalDate yesterday = LocalDate.now(ZoneId.of("Asia/Shanghai")).minusDays(1);
        String dailyStartTime = yesterday.atStartOfDay().format(TIME_FORMAT);    // 00:00:00
        String dailyEndTime = yesterday.atTime(23, 59, 59).format(TIME_FORMAT);   // 23:59:59
        // 日
        String dayOrMonth = "1";
        // 95带宽值/日
        EpsInitialTrafficData queryParam = new EpsInitialTrafficData();
        queryParam.setDayOrMonth(dayOrMonth);
        InitialSwitchInfoDetails initialSwitchInfoDetails = new InitialSwitchInfoDetails();
        initialSwitchInfoDetails.setDayOrMonth(dayOrMonth);
        // 顺序执行链
        CompletableFuture.runAsync(() -> executeWithLog("业务带宽1000",
                () -> epsInitialTrafficDataService.calculateBusiness95BandwidthDaily(queryParam, dailyStartTime, dailyEndTime, "1000")))
        .thenRun(() -> executeWithLog("业务带宽1024",
                () -> epsInitialTrafficDataService.calculateBusiness95BandwidthDaily(queryParam, dailyStartTime, dailyEndTime, "1024")))
        .thenRun(() -> executeWithLog("交换机带宽1000",
                () -> initialSwitchInfoDetailsService.calculateSwitch95BandwidthDaily(initialSwitchInfoDetails, dailyStartTime, dailyEndTime, "1000")))
        .thenRun(() -> executeWithLog("交换机带宽1024",
                () -> initialSwitchInfoDetailsService.calculateSwitch95BandwidthDaily(initialSwitchInfoDetails, dailyStartTime, dailyEndTime, "1024")));
    }
    // 每天5点04执行 计算金山95带宽值/日
    @Scheduled(cron = "0 4 5 * * ?", zone = "Asia/Shanghai")
    public void calculateJinShan95() {
        // 获取昨天的日期范围（北京时间）
        LocalDate yesterday = LocalDate.now(ZoneId.of("Asia/Shanghai")).minusDays(1);
        String dailyStartTime = yesterday.atStartOfDay().format(TIME_FORMAT);    // 00:00:00
        String dailyEndTime = yesterday.atTime(23, 59, 59).format(TIME_FORMAT);   // 23:59:59
        // 日
        String dayOrMonth = "1";
        // 95带宽值/日
        EpsInitialTrafficData queryParam = new EpsInitialTrafficData();
        queryParam.setDayOrMonth(dayOrMonth);
        InitialSwitchInfoDetails initialSwitchInfoDetails = new InitialSwitchInfoDetails();
        initialSwitchInfoDetails.setDayOrMonth(dayOrMonth);
        // 顺序执行链
        CompletableFuture.runAsync(() -> executeWithLog("金山业务带宽1000",
                        () -> epsInitialTrafficDataService.calculate95ByJinShan(queryParam, dailyStartTime, dailyEndTime, "1000")))
                .thenRun(() -> executeWithLog("金山业务带宽1024",
                        () -> epsInitialTrafficDataService.calculate95ByJinShan(queryParam, dailyStartTime, dailyEndTime, "1024")));
    }

    // 每月1号0点执行 计算95带宽值/月
    @Scheduled(cron = "0 3 0 1 * ?", zone = "Asia/Shanghai")
    public void calculateMonthlyBandwidthTasks() {
        // 获取上个月的日期范围
        LocalDate lastMonth = LocalDate.now(ZoneId.of("Asia/Shanghai")).minusMonths(1);
        LocalDate firstDayOfMonth = lastMonth.withDayOfMonth(1);
        LocalDate lastDayOfMonth = lastMonth.withDayOfMonth(lastMonth.lengthOfMonth());

        String monthlyStartTime = firstDayOfMonth.atStartOfDay().format(TIME_FORMAT);
        String monthlyEndTime = lastDayOfMonth.atTime(23, 59, 59).format(TIME_FORMAT);

        // 链式顺序执行（无额外日志封装）
        CompletableFuture.runAsync(() -> calculateServerMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1000"))
                .thenRun(() -> calculateServerMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1024"))
                .thenRun(() -> calculateSwitchMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1000"))
                .thenRun(() -> calculateSwitchMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1024"))
                .thenRun(() -> calculateServerAvgMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1000"))
                .thenRun(() -> calculateServerAvgMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1024"))
                .thenRun(() -> calculateSwitchAvgMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1000"))
                .thenRun(() -> calculateSwitchAvgMonthlyBandwidth(monthlyStartTime, monthlyEndTime, "1024"))
                .exceptionally(e -> {
                    log.error("月度带宽计算链执行异常", e); // 仅保留最终异常捕获
                    return null;
                });
    }

    /**
     * 执行任务日志
     */
    private void executeWithLog(String taskName, Runnable task) {
        log.info("开始执行: {}", taskName);
        try {
            task.run();
        } catch (Exception e) {
            log.error("{} 执行失败", taskName, e);
            throw e; // 可选：是否终止后续任务
        }
        log.info("{} 执行完成", taskName);
    }
    /**
     * 计算服务器月95带宽值
     */
    private void calculateServerMonthlyBandwidth(String monthlyStartTime, String monthlyEndTime, String calculationMode) {
        log.info("开始计算服务器月95带宽值...");
        try {
            String dayOrMonth = "2";
            EpsInitialTrafficData queryParam = new EpsInitialTrafficData();
            queryParam.setDayOrMonth(dayOrMonth);
            epsInitialTrafficDataService.calculateBusiness95BandwidthDaily(queryParam, monthlyStartTime, monthlyEndTime, calculationMode);
            log.info("服务器月95带宽值计算完成");
        } catch (Exception e) {
            log.error("计算服务器月95带宽值失败", e);
        }
    }

    /**
     * 计算交换机月95带宽值
     */
    private void calculateSwitchMonthlyBandwidth(String monthlyStartTime, String monthlyEndTime, String calculationMode) {
        log.info("开始计算交换机月95带宽值...");
        try {
            String dayOrMonth = "2";
            InitialSwitchInfoDetails queryParam = new InitialSwitchInfoDetails();
            queryParam.setDayOrMonth(dayOrMonth);
            initialSwitchInfoDetailsService.calculateSwitch95BandwidthDaily(queryParam, monthlyStartTime, monthlyEndTime, calculationMode);
            log.info("交换机月95带宽值计算完成");
        } catch (Exception e) {
            log.error("计算交换机月95带宽值失败", e);
        }
    }

    /**
     * 计算服务器月平均95带宽值
     */
    private void calculateServerAvgMonthlyBandwidth(String monthlyStartTime, String monthlyEndTime, String calculationMode) {
        log.info("开始计算服务器月平均95带宽值...");
        try {
            EpsNodeBandwidth epsNodeBandwidth = new EpsNodeBandwidth();
            epsNodeBandwidth.setStartTime(monthlyStartTime);
            epsNodeBandwidth.setEndTime(monthlyEndTime);

            List<AllInterfaceName> snList = allInterfaceNameService.getAllDeviceSn(new AllInterfaceName());
            for (AllInterfaceName allInterfaceName : snList) {
                processServerAvgBandwidth(epsNodeBandwidth, allInterfaceName, calculationMode);
            }
            log.info("服务器月平均95带宽值计算完成");
        } catch (Exception e) {
            log.error("计算服务器月平均95带宽值失败", e);
        }
    }

    /**
     * 处理单个服务器的平均带宽计算
     */
    private void processServerAvgBandwidth(EpsNodeBandwidth epsNodeBandwidth, AllInterfaceName allInterfaceName, String calculationMode) {
        final String clientId = allInterfaceName.getClientId();

        try {
            // 1. 设置基础设备信息
            epsNodeBandwidth.setClientId(clientId);
            // 查询业务变更记录
            EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
            changeQuery.setClientId(clientId);
            changeQuery.setStartTime(epsNodeBandwidth.getStartTime());
            changeQuery.setEndTime(epsNodeBandwidth.getEndTime());

            List<EpsMethodChangeRecord> records = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(changeQuery);

            // 按businessCode分组处理（修复null key问题）
            if (!records.isEmpty()) {
                Map<String, List<EpsMethodChangeRecord>> groupedRecords = records.stream()
                        .filter(record -> record.getBusinessCode() != null) // 过滤掉businessCode为null的记录
                        .collect(Collectors.groupingBy(EpsMethodChangeRecord::getBusinessCode));

                // 处理每个业务分组
                for (Map.Entry<String, List<EpsMethodChangeRecord>> entry : groupedRecords.entrySet()) {
                    String businessCode = entry.getKey();
                    // 取第一个有效业务名称（同businessCode的业务名称应该相同）
                    String businessName = entry.getValue().stream()
                            .filter(r -> r.getBusinessName() != null)
                            .findFirst()
                            .map(EpsMethodChangeRecord::getBusinessName)
                            .orElse("未知业务");

                    // 创建业务带宽对象
                    EpsNodeBandwidth bandwidthWithBiz = new EpsNodeBandwidth();
                    bandwidthWithBiz.setClientId(clientId);
                    bandwidthWithBiz.setCalculationMode(calculationMode);
                    bandwidthWithBiz.setStartTime(epsNodeBandwidth.getStartTime());
                    bandwidthWithBiz.setEndTime(epsNodeBandwidth.getEndTime());
                    bandwidthWithBiz.setBusinessId(businessCode);
                    bandwidthWithBiz.setBusinessName(businessName);
                    bandwidthWithBiz.setResourceType("1");

                    // 执行计算
                    epsNodeBandwidthService.calculateAvg(bandwidthWithBiz);
                }

                // 处理businessCode为null的记录（如果有）
                List<EpsMethodChangeRecord> nullBusinessRecords = records.stream()
                        .filter(record -> record.getBusinessCode() == null)
                        .collect(Collectors.toList());

                if (!nullBusinessRecords.isEmpty()) {
                    log.warn("服务器 {} 有 {} 条记录的businessCode为null", clientId, nullBusinessRecords.size());
                    // 可以选择记录日志或进行其他处理
                }

                return; // 业务变更处理完成后直接返回
            }
            String businessCode = null;
            String businessName = null;
            // 查询绑定的业务
            EpsMethodChangeRecord queryParam = new EpsMethodChangeRecord();
            queryParam.setClientId(clientId);
            List<EpsMethodChangeRecord> recordList = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(queryParam);
            if(!recordList.isEmpty()){
                EpsMethodChangeRecord record = recordList.stream()
                        .findFirst()
                        .orElse(null);
                businessCode = record.getBusinessCode();
                businessName = record.getBusinessName();
            }
            // 5. 处理正常情况（无业务变更或无需处理变更）
            EpsNodeBandwidth normalBandwidth = new EpsNodeBandwidth();
            normalBandwidth.setClientId(clientId);
            normalBandwidth.setCalculationMode(calculationMode);
            normalBandwidth.setStartTime(epsNodeBandwidth.getStartTime());
            normalBandwidth.setEndTime(epsNodeBandwidth.getEndTime());
            normalBandwidth.setBusinessId(businessCode);
            normalBandwidth.setBusinessName(businessName);
            normalBandwidth.setResourceType("1");
            epsNodeBandwidthService.calculateAvg(normalBandwidth);

        } catch (Exception e) {
            log.error("处理服务器 {} 平均带宽失败", clientId, e);
        }
    }

    /**
     * 计算交换机月平均95带宽值
     */
    private void calculateSwitchAvgMonthlyBandwidth(String monthlyStartTime, String monthlyEndTime, String calculationMode) {
        log.info("开始计算交换机月平均95带宽值...");
        try {
            EpsNodeBandwidth epsNodeBandwidth = new EpsNodeBandwidth();
            epsNodeBandwidth.setStartTime(monthlyStartTime);
            epsNodeBandwidth.setEndTime(monthlyEndTime);

            List<AllInterfaceName> switchSnList = allInterfaceNameService.getAllSwitchSn(new AllInterfaceName());
            for (AllInterfaceName switchSnMsg : switchSnList) {
                processSwitchAvgBandwidth(epsNodeBandwidth, switchSnMsg, calculationMode);
            }
            log.info("交换机月平均95带宽值计算完成");
        } catch (Exception e) {
            log.error("计算交换机月平均95带宽值失败", e);
        }
    }

    /**
     * 处理单个交换机的平均带宽计算
     */
    private void processSwitchAvgBandwidth(EpsNodeBandwidth epsNodeBandwidth, AllInterfaceName switchSnMsg, String calculationMode) {
        final String clientId = switchSnMsg.getClientId();

        try {
            // 1. 查询交换机拓扑信息
            RmEpsTopologyManagement managementQuery = new RmEpsTopologyManagement();
            managementQuery.setClientId(clientId);
            List<RmEpsTopologyManagement> topologyList = rmEpsTopologyManagementService.selectRmEpsTopologyManagementList(managementQuery);
            if(!topologyList.isEmpty()){
                for (RmEpsTopologyManagement topology : topologyList) {
                    epsNodeBandwidth.setClientId(clientId);
                    epsNodeBandwidth.setInterfaceName(topology.getInterfaceName());

                    // 3. 判断连接设备类型
                    boolean isServerConnected = "1".equals(topology.getConnectedDeviceType());

                    // 4. 处理服务器连接的情况
                    if (isServerConnected && topology.getServerClientId() != null) {
                        String serverClientId = topology.getServerClientId();
                        String serverSn = topology.getServerSn();
                        // 查询业务变更记录
                        EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
                        changeQuery.setClientId(serverClientId);
                        changeQuery.setStartTime(epsNodeBandwidth.getStartTime());
                        changeQuery.setEndTime(epsNodeBandwidth.getEndTime());
                        List<EpsMethodChangeRecord> records = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(changeQuery);

                        // 按businessCode分组处理
                        if (!records.isEmpty()) {
                            Map<String, List<EpsMethodChangeRecord>> groupedRecords = records.stream()
                                    .filter(record -> record.getBusinessCode() != null) // 过滤掉businessCode为null的记录
                                    .collect(Collectors.groupingBy(EpsMethodChangeRecord::getBusinessCode));

                            // 处理每个业务分组
                            for (Map.Entry<String, List<EpsMethodChangeRecord>> entry : groupedRecords.entrySet()) {
                                String businessCode = entry.getKey();
                                List<EpsMethodChangeRecord> businessRecords = entry.getValue();

                                // 取第一个有效业务名称
                                String businessName = businessRecords.stream()
                                        .filter(r -> r.getBusinessName() != null)
                                        .findFirst()
                                        .map(EpsMethodChangeRecord::getBusinessName)
                                        .orElse("未知业务");

                                // 创建业务带宽对象
                                EpsNodeBandwidth bandwidthWithBiz = new EpsNodeBandwidth();
                                bandwidthWithBiz.setClientId(clientId);
                                bandwidthWithBiz.setCalculationMode(calculationMode);
                                bandwidthWithBiz.setInterfaceName(topology.getInterfaceName());
                                bandwidthWithBiz.setHardwareSn(serverSn);
                                bandwidthWithBiz.setUplinkSwitch(topology.getSwitchName());
                                bandwidthWithBiz.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
                                bandwidthWithBiz.setStartTime(epsNodeBandwidth.getStartTime());
                                bandwidthWithBiz.setEndTime(epsNodeBandwidth.getEndTime());
                                bandwidthWithBiz.setBusinessId(businessCode);
                                bandwidthWithBiz.setBusinessName(businessName);
                                bandwidthWithBiz.setResourceType("2");
                                bandwidthWithBiz.setServerClientId(serverClientId);
                                // 执行计算
                                epsNodeBandwidthService.calculateAvg(bandwidthWithBiz);
                            }

                            // 处理businessCode为null的记录（如果有）
                            List<EpsMethodChangeRecord> nullBusinessRecords = records.stream()
                                    .filter(record -> record.getBusinessCode() == null)
                                    .collect(Collectors.toList());

                            if (!nullBusinessRecords.isEmpty()) {
                                log.warn("交换机 {} 有 {} 条记录的businessCode为null", clientId, nullBusinessRecords.size());
                                // 可以选择记录日志或进行其他处理
                            }

                            return; // 业务变更处理完成后直接返回
                        }else{
                            String businessCode = null;
                            String businessName = null;
                            // 查询绑定的业务
                            EpsMethodChangeRecord queryParam = new EpsMethodChangeRecord();
                            queryParam.setClientId(clientId);
                            queryParam.setTrafficPort(topology.getServerPort());
                            List<EpsMethodChangeRecord> recordList = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(queryParam);
                            if(!recordList.isEmpty()){
                                EpsMethodChangeRecord record = recordList.stream()
                                        .findFirst()
                                        .orElse(null);
                                businessCode = record.getBusinessCode();
                                businessName = record.getBusinessName();
                            }
                            // 5. 处理普通情况（无变更记录）
                            EpsNodeBandwidth normalBandwidth = new EpsNodeBandwidth();
                            normalBandwidth.setClientId(clientId);
                            normalBandwidth.setBusinessId(businessCode);
                            normalBandwidth.setBusinessName(businessName);
                            normalBandwidth.setCalculationMode(calculationMode);
                            normalBandwidth.setInterfaceName(topology.getInterfaceName());
                            normalBandwidth.setHardwareSn(topology.getServerSn());
                            normalBandwidth.setUplinkSwitch(topology.getSwitchName());
                            normalBandwidth.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
                            normalBandwidth.setStartTime(epsNodeBandwidth.getStartTime());
                            normalBandwidth.setEndTime(epsNodeBandwidth.getEndTime());
                            normalBandwidth.setResourceType("2");
                            normalBandwidth.setServerClientId(serverClientId);
                            epsNodeBandwidthService.calculateAvg(normalBandwidth);
                            return;
                        }
                    }
                    // 5. 处理机房出口情况
                    EpsNodeBandwidth normalBandwidth = new EpsNodeBandwidth();
                    normalBandwidth.setClientId(clientId);
                    normalBandwidth.setCalculationMode(calculationMode);
                    normalBandwidth.setInterfaceName(topology.getInterfaceName());
                    normalBandwidth.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
                    normalBandwidth.setStartTime(epsNodeBandwidth.getStartTime());
                    normalBandwidth.setEndTime(epsNodeBandwidth.getEndTime());
                    normalBandwidth.setResourceType("2");
                    epsNodeBandwidthService.calculateAvg(normalBandwidth);
                }
            }else{
                log.warn("未检测到拓扑配置，交换机clientId：{}", clientId);
            }
        } catch (Exception e) {
            log.error("处理交换机 {} 平均带宽失败", clientId, e);
        }
    }
}
