package com.zc.business.controller;

import com.alibaba.fastjson.JSONArray;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StakeMarkUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.zc.business.domain.*;
import com.zc.business.domain.export.RealTimeTrafficFlow;
import com.zc.business.domain.export.SectionTrafficIndexAnalysis;
import com.zc.business.domain.export.SectionTrafficRanking;
import com.zc.business.domain.export.TrafficPeriodAnalysis;
import com.zc.business.enums.StakeMarkRange;
import com.zc.business.enums.UniversalEnum;
import com.zc.business.request.DcTrafficMetricsDataRequest;
import com.zc.business.request.DcTrafficSectionDataRequest;
import com.zc.business.service.*;
import com.zc.common.core.httpclient.exception.HttpException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 交通数据统计
 *
 * @author xiepufeng
 */
@Api(tags = "交通数据统计")
@RestController
@RequestMapping("/business/traffic-statistics")
public class DcTrafficStatisticsController  extends BaseController {

    @Autowired
    private IDcTrafficSectionStatisticsService dcTrafficSectionStatisticsService;

    @Autowired
    private IDcTrafficStatisticsService dcTrafficStatisticsService;

    @Autowired
    private IDcTollStationStatisticsDataService dcTollStationStatisticsDataService;

    @Autowired
    private IDcGantryStatisticsDataService dcGantryStatisticsDataService;

    @Autowired
    private IDcGantryMetricsStatisticsDataService dcGantryMetricsStatisticsDataService;

    /**
     * 获取当前交通截面数据
     *
     * @param request 请求参数,封装了对于交通截面数据查询的详细要求
     * @return 返回一个AjaxResult对象,其中包含了查询结果。如果查询成功,则结果中封装了当前交通截面的数据(DcTrafficSectionData类型)
     */
    @ApiOperation("获取当前交通截面数据")
    @GetMapping("/current/sections")
    public AjaxResult currentSections(DcTrafficSectionDataRequest request){
        // 调用服务层方法,查询当前交通截面数据
        List<DcTrafficSectionData> dcTrafficMetricsData = dcTrafficSectionStatisticsService.currentSections(request);
        // 将查询结果封装为AjaxResult对象返回
        return AjaxResult.success(dcTrafficMetricsData);
    }

    /**
     * 获取历史交通截面数据
     *
     * @param request 包含交通截面数据请求参数的对象
     * @return 返回一个包含历史交通截面数据的AjaxResult对象
     */
    @ApiOperation("获取历史交通截面数据")
    @GetMapping("/history/sections")
    public AjaxResult historySections(DcTrafficSectionDataRequest request){
        // 调用服务层方法,获取历史交通截面的统计数据
        List<DcTrafficSectionData> dcTrafficMetricsData = dcTrafficSectionStatisticsService.historySections(request);
        // 将获取到的历史交通截面数据封装成AjaxResult对象并返回
        return AjaxResult.success(dcTrafficMetricsData);
    }


    /**
     * 获取当前交通特征指数
     *
     * @param request 请求参数,封装了获取交通指标所需的数据和条件
     * @return 返回当前交通特征指数的数据结果,使用AjaxResult包装
     */
    @ApiOperation("获取当前交通特征指数")
    @GetMapping("/current/metrics")
    public AjaxResult currentTrafficMetrics(DcTrafficMetricsDataRequest request){
        // 调用服务层方法,获取当前交通指标数据
        List<DcTrafficMetricsData> dcTrafficMetricsData = dcTrafficSectionStatisticsService.currentTrafficMetrics(request);
        // 将获取到的交通指标数据封装为成功的结果并返回
        return AjaxResult.success(dcTrafficMetricsData);
    }

    /**
     * 获取历史交通特征指数
     *
     * @param request 请求参数,包含需要查询的历史交通特征指数的详细信息
     * @return 返回一个AjaxResult对象,其中包含了查询结果的成功状态和历史交通特征指数数据列表
     */
    @ApiOperation("获取历史交通特征指数")
    @GetMapping("/history/metrics")
    public AjaxResult historyTrafficMetrics(DcTrafficMetricsDataRequest request){
        // 调用服务层方法,查询历史交通特征指数数据
        List<DcTrafficMetricsData> dcTrafficMetricsDataList = dcTrafficSectionStatisticsService.historyTrafficMetrics(request);
        // 将查询结果封装成成功响应并返回
        return AjaxResult.success(dcTrafficMetricsDataList);
    }

    /**
     * 获取当前拥堵路段
     *
     * @param direction 交通方向,指定查询哪个方向的拥堵路段。具体方向的定义根据实际业务而定。
     * @return 返回一个AjaxResult对象,其中包含了查询结果。如果查询成功,则结果中封装了当前拥堵路段的数据列表。
     */
    @ApiOperation("获取当前拥堵路段")
    @GetMapping("/current/congested")
    public AjaxResult currentCongestedSection(Byte direction){
        // 调用服务层方法,获取当前交通指标数据
        List<DcCongestedSectionData> dcTrafficMetricsData = dcTrafficSectionStatisticsService.currentCongestedSection(direction);
        // 将获取到的交通指标数据封装为成功的结果并返回
        return AjaxResult.success(dcTrafficMetricsData);
    }


    /**
     * 获取收费站统计数据
     *
     * @param request 包含查询条件的请求对象,用于筛选历史收费站统计数据
     * @return 返回一个AjaxResult对象,其中包含了查询到的收费站统计数据列表
     */
        @ApiOperation("获取收费站统计数据")
    @GetMapping("/history/toll-station")
    public AjaxResult historyTollStation(DcTollStationStatisticsData request){
        // 调用服务层方法,根据请求条件查询历史车收费站数据
        List<DcTollStationStatisticsData> dcStatisticsData = dcTollStationStatisticsDataService.tollStationData(request);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(dcStatisticsData);
    }

    /**
     * 获取累计车流量
     *
     * @param request 包含查询条件的请求对象,用于筛选历史收费站统计数据
     * @return 返回一个AjaxResult对象,其中包含了查询到的收费站统计数据列表
     */
    @ApiOperation("获取累计车流量")
    @GetMapping("/history/accumulated-flow")
    public AjaxResult accumulatedFlow(DcTollStationStatisticsData request){
        // 调用服务层方法,根据请求条件查询历史车收费站数据
        List<DcTollStationStatisticsData> dcStatisticsData = dcTollStationStatisticsDataService.accumulatedFlow(request);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(dcStatisticsData);
    }

    /**
     * 获取门架统计数据
     *
     * @param request 包含查询条件的请求对象,用于筛选历史门架统计数据
     * @return 返回一个AjaxResult对象,其中包含了查询到的门架统计数据列表
     */
    @ApiOperation("获取门架统计数据")
    @GetMapping("/history/gantry")
    public AjaxResult historyGantryData(DcGantryStatisticsData request){
        // 调用服务层方法,根据请求条件查询历史车门架数据
        List<DcGantryStatisticsData> dcStatisticsData = dcGantryStatisticsDataService.gantryData(request);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(dcStatisticsData);
    }

    /**
     * 交通流统计 列表
     * @param startDate
     * @param endDate
     * @param direction
     * @param periodType
     * @return
     */
        @ApiOperation("交通流统计")
    @GetMapping("/history/trafficFlowStatistics")
    public TableDataInfo trafficFlowStatistics(String startDate, String endDate, String direction, String periodType){
            startPage();
            List<Map<String,String>> mapList = dcGantryStatisticsDataService.trafficFlowStatistics(startDate,endDate,direction,periodType);
        // 将查询结果封装为成功响应并返回
        return getDataTable(mapList);
    }



/**
 * 全路段双向实时车流量
 * @param startDate 时间
 * @param direction 方向
 * @param periodType 时间粒子
 */
@ApiOperation("全路段车流量状况分析")
@GetMapping("/history/realTimeTrafficFlow")
public AjaxResult realTimeTrafficFlow(String startDate, String direction,String periodType ){
    List<Map<String,String>> mapList = dcGantryStatisticsDataService.realTimeTrafficFlow(startDate,direction,periodType);
    // 将查询结果封装为成功响应并返回
    return AjaxResult.success(mapList);
}

    /**
     * 导出全路段双向实时车流量
     * @param startDate 时间
     * @param direction 方向
     * @param periodType 时间粒子
     */
    @ApiOperation(value="导出全路段车流量状况分析",tags = {"ECharts导出"})
    @GetMapping("/history/exportRealTimeTrafficFlow")
    public void exportRealTimeTrafficFlow(HttpServletResponse response,String startDate, String direction,String periodType ){
        if (StringUtils.isEmpty(startDate) || StringUtils.isEmpty(direction) || StringUtils.isEmpty(periodType)){
            return;
        }
        String endDate = UniversalEnum.EMPTY_STRING.getValue();
        if (UniversalEnum.FOUR.getValue().equals(periodType)){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(UniversalEnum.TIME_FORMAT_YEARS_MONTH_DAY.getValue());
            LocalDate inputDate = LocalDate.parse(startDate, formatter);
            // 获取一年前的日期
            LocalDate end = inputDate.minusYears(UniversalEnum.ONE.getNumber());
            endDate = end.format(formatter);
        } else if (UniversalEnum.THREE.getValue().equals(periodType)){
            String[] parts = startDate.split(UniversalEnum.SHORT_BAR.getValue());
            int year = Integer.parseInt(parts[UniversalEnum.ZERO.getNumber()]);
            int month = Integer.parseInt(parts[UniversalEnum.ONE.getNumber()]);

            // 计算一年前的年份和月份
            year -= UniversalEnum.ONE.getNumber();
            // 如果计算后月份为0,则调整为上一年的12月
            if (month == UniversalEnum.ZERO.getNumber()) {
                year -= UniversalEnum.ONE.getNumber();
                month = UniversalEnum.TWELVE.getNumber();
            }
            endDate = String.format("%04d-%02d", year, month);
        } else if (UniversalEnum.ONE.getValue().equals(periodType)){
            int year = Integer.parseInt(startDate) - UniversalEnum.ONE.getNumber();
            endDate = String.valueOf(year);
        }


        List<RealTimeTrafficFlow> list = new ArrayList<>();
        List<Map<String,String>> mapList = dcGantryStatisticsDataService.realTimeTrafficFlow(startDate,direction,periodType);
        List<Map<String,String>> lastList = dcGantryStatisticsDataService.realTimeTrafficFlow(endDate,direction,periodType);
        mapList = mapList.stream().sorted(
                Comparator.comparing(map -> {
                    String stakeMark = map.get("stake_make");
                    return StakeMarkUtils.formatMetre(stakeMark);
                }))
                .collect(Collectors.toList());
        lastList = lastList.stream().sorted(
                Comparator.comparing(map -> {
                    String stakeMark = map.get("stake_make");
                    return StakeMarkUtils.formatMetre(stakeMark);
                }))
                .collect(Collectors.toList());
        for (int i = 0; i < mapList.size(); i++) {
            RealTimeTrafficFlow realTimeTrafficFlow = new RealTimeTrafficFlow();
            realTimeTrafficFlow.setName(mapList.get(i).get("name"));
            realTimeTrafficFlow.setTotalPassengerFlow(String.valueOf(mapList.get(i).get("totalPassengerFlow")));
            realTimeTrafficFlow.setTypeSpecialVehicleFlow(String.valueOf(mapList.get(i).get("typeSpecialVehicleFlow")));
            realTimeTrafficFlow.setTypeTruckFlow(String.valueOf(mapList.get(i).get("typeTruckFlow")));
            realTimeTrafficFlow.setLastYearTotal(String.valueOf(lastList.get(i).get("volume")));
            list.add(realTimeTrafficFlow);
        }

        ExcelUtil<RealTimeTrafficFlow> util = new ExcelUtil<>(RealTimeTrafficFlow.class);
        util.exportExcel(response, list, UniversalEnum.THE_WHOLE_SECTION_TWO_WAY_REAL_TIME_TRAFFIC_FLOW.getValue());
        // 将查询结果封装为成功响应并返回
    }
    /**
     * 车流量时段分析
     * @param startDate 时间
     * @param direction 方向
     * @param periodType 时间粒子
     */
    @ApiOperation("车流量时段分析")
    @GetMapping("/history/trafficPeriodAnalysis")
    public AjaxResult trafficPeriodAnalysis(String startDate, String direction,String periodType ){
        List<Map<String,String>> mapList = dcGantryStatisticsDataService.trafficPeriodAnalysis(startDate,direction,periodType);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(mapList);
    }

    /**
     * 导出车流量时段分析
     * @param startDate 时间
     * @param direction 方向
     * @param periodType 时间粒子
     */
    @ApiOperation(value="导出车流量时段分析",tags = {"ECharts导出"})
    @GetMapping("/history/exportTrafficPeriodAnalysis")
    public void exportTrafficPeriodAnalysis(HttpServletResponse response,String startDate, String direction,String periodType ){
        if (StringUtils.isEmpty(startDate) || StringUtils.isEmpty(direction) || StringUtils.isEmpty(periodType)){
            return;
        }
        String endDate = UniversalEnum.EMPTY_STRING.getValue();
        if (UniversalEnum.FOUR.getValue().equals(periodType)){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(UniversalEnum.TIME_FORMAT_YEARS_MONTH_DAY.getValue());
            LocalDate inputDate = LocalDate.parse(startDate, formatter);
            // 获取一年前的日期
            LocalDate end = inputDate.minusYears(1);
            endDate = end.format(formatter);
        } else if (UniversalEnum.THREE.getValue().equals(periodType)){
            String[] parts = startDate.split(UniversalEnum.SHORT_BAR.getValue());
            int year = Integer.parseInt(parts[UniversalEnum.ZERO.getNumber()]);
            int month = Integer.parseInt(parts[UniversalEnum.ONE.getNumber()]);

            // 计算一年前的年份和月份
            year -= UniversalEnum.ONE.getNumber();
            // 如果计算后月份为0,则调整为上一年的12月
            if (month == UniversalEnum.ZERO.getNumber()) {
                year -= UniversalEnum.ONE.getNumber();
                month = UniversalEnum.TWELVE.getNumber();
            }
            endDate = String.format("%04d-%02d", year, month);
        } else if (UniversalEnum.ONE.getValue().equals(periodType)){
            int year = Integer.parseInt(startDate) - UniversalEnum.ONE.getNumber();
            endDate = String.valueOf(year);
        }


        List<TrafficPeriodAnalysis> list = new ArrayList<>();
        List<Map<String,String>> mapList = dcGantryStatisticsDataService.trafficPeriodAnalysis(startDate,direction,periodType);
        Map<String,String> mapData = new HashMap<>();
        if (mapList != null && mapList.size() > UniversalEnum.ZERO.getNumber()){
            for (Map<String, String> item : mapList) {
                mapData.put(item.get("statisticalHour"),item.get("trafficVolume"));
            }
        }
        List<Map<String,String>> lastList = dcGantryStatisticsDataService.trafficPeriodAnalysis(endDate,direction,periodType);
        Map<String,String> lastData = new HashMap<>();
        if (lastList != null && lastList.size() > UniversalEnum.ZERO.getNumber()){
            for (Map<String, String> item : lastList) {
                lastData.put(item.get("statisticalHour"),item.get("trafficVolume"));
            }
        }

        for (int i = UniversalEnum.ZERO.getNumber(); i < UniversalEnum.TWENTY_FOUR.getNumber(); i++) {
            TrafficPeriodAnalysis trafficPeriodAnalysis = new TrafficPeriodAnalysis();
            trafficPeriodAnalysis.setTime(i + "点至" + (i+UniversalEnum.ONE.getNumber()) + "点");
            trafficPeriodAnalysis.setCurrentData(mapData.getOrDefault(String.valueOf(i), UniversalEnum.ZERO.getValue()));

            trafficPeriodAnalysis.setContemporaneousData(lastData.getOrDefault(String.valueOf(i), UniversalEnum.ZERO.getValue()));
            list.add(trafficPeriodAnalysis);
        }

        ExcelUtil<TrafficPeriodAnalysis> util = new ExcelUtil<>(TrafficPeriodAnalysis.class);
        util.exportExcel(response, list, UniversalEnum.TRAFFIC_PERIOD_ANALYSIS.getValue());
    }

    @ApiOperation("断面车流量排名")
    @GetMapping("/history/sectionTrafficRanking")
    public AjaxResult sectionTrafficRanking(String startDate, String direction,String periodType ){
        List<Map<String, String>> dcStatisticsData = dcGantryStatisticsDataService.sectionTrafficRanking(startDate,direction,periodType);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(dcStatisticsData);
    }



    /**
     * 导出断面车流量排名
     * @param startDate 时间
     * @param direction 方向
     * @param periodType 时间粒子
     */
    @ApiOperation(value="导出断面车流量排名",tags = {"ECharts导出"})
    @GetMapping("/history/exportSectionTrafficRanking")
    public void exportSectionTrafficRanking(HttpServletResponse response,String startDate, String direction,String periodType ){
        List<SectionTrafficRanking> list = new ArrayList<>();
        List<Map<String, String>> dcStatisticsData = dcGantryStatisticsDataService.sectionTrafficRanking(startDate,direction,periodType);
        for (int i = UniversalEnum.ZERO.getNumber(); i < dcStatisticsData.size(); i++) {
            SectionTrafficRanking sectionTrafficRanking = new SectionTrafficRanking();
            sectionTrafficRanking.setRank(i + UniversalEnum.ONE.getNumber());
            sectionTrafficRanking.setFacilityName(dcStatisticsData.get(i).get("facilityName"));
            sectionTrafficRanking.setNumber(String.valueOf(dcStatisticsData.get(i).get("trafficVolume")));
            list.add(sectionTrafficRanking);
        }

        ExcelUtil<SectionTrafficRanking> util = new ExcelUtil<>(SectionTrafficRanking.class);
        util.exportExcel(response, list, UniversalEnum.SECTION_TRAFFIC_RANKING.getValue());

    }

    /**
     * sectionTrafficIndexAnalysis
     * @param startDate 时间
     * @param direction 方向
     * @param periodType 时间粒子
     * @param ranking 排名 1 饱和度 2拥挤度 3交通特征指数
     *
     */
    @ApiOperation("路段交通指标分析")
    @GetMapping("/history/sectionTrafficIndexAnalysis")
    public AjaxResult sectionTrafficIndexAnalysis(String startDate, String direction,String periodType,Long ranking ){
       List<Map<String, Object>>  mapList = dcGantryMetricsStatisticsDataService.sectionTrafficIndexAnalysis(startDate,direction,periodType,ranking);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(mapList);
    }

    @ApiOperation(value="导出路段交通指标分析",tags = {"ECharts导出"})
    @GetMapping("/history/exportSectionTrafficIndexAnalysis")
    public void exportSectionTrafficIndexAnalysis(HttpServletResponse response,String startDate, String direction,String periodType,Long ranking){
        List<SectionTrafficIndexAnalysis> list = new ArrayList<>();

        String endDate = UniversalEnum.EMPTY_STRING.getValue();
        if (UniversalEnum.FOUR.getValue().equals(periodType)){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(UniversalEnum.TIME_FORMAT_YEARS_MONTH_DAY.getValue());
            LocalDate inputDate = LocalDate.parse(startDate, formatter);
            // 获取一年前的日期
            LocalDate end = inputDate.minusYears(1);
            endDate = end.format(formatter);
        } else if (UniversalEnum.THREE.getValue().equals(periodType)){
            String[] parts = startDate.split(UniversalEnum.SHORT_BAR.getValue());
            int year = Integer.parseInt(parts[UniversalEnum.ZERO.getNumber()]);
            int month = Integer.parseInt(parts[UniversalEnum.ONE.getNumber()]);

            // 计算一年前的年份和月份
            year -= UniversalEnum.ONE.getNumber();
            // 如果计算后月份为0,则调整为上一年的12月
            if (month == UniversalEnum.ZERO.getNumber()) {
                year -= UniversalEnum.ONE.getNumber();
                month = UniversalEnum.TWELVE.getNumber();
            }
            endDate = String.format("%04d-%02d", year, month);
        } else if (UniversalEnum.ONE.getValue().equals(periodType)){
            int year = Integer.parseInt(startDate) - UniversalEnum.ONE.getNumber();
            endDate = String.valueOf(year);
        }
        List<Map<String, Object>>  thisYearList = dcGantryMetricsStatisticsDataService.sectionTrafficIndexAnalysis(startDate,direction,periodType,ranking);
        Map<String,List<Map<String, Object>>> thisYearData = thisYearList.stream().collect(Collectors.groupingBy(item -> item.get("groupName").toString()));
        List<Map<String, Object>>  lastYearList = dcGantryMetricsStatisticsDataService.sectionTrafficIndexAnalysis(endDate,direction,periodType,ranking);
        Map<String,List<Map<String, Object>>> lastYearData = lastYearList.stream().collect(Collectors.groupingBy(item -> item.get("groupName").toString()));

        for (StakeMarkRange value : StakeMarkRange.values()) {
            String sectionName = value.getDescription();
            SectionTrafficIndexAnalysis sectionTrafficIndexAnalysis = new SectionTrafficIndexAnalysis();
            sectionTrafficIndexAnalysis.setName(value.getDescription());
            if (thisYearData.containsKey(sectionName)){
                Map<String, Object> sectionData = thisYearData.get(sectionName).get(UniversalEnum.ZERO.getNumber());
                sectionTrafficIndexAnalysis.setCrowdingRate(sectionData.get("crowdingRate").toString());
                sectionTrafficIndexAnalysis.setSaturationRate(sectionData.get("saturationRate").toString());
                sectionTrafficIndexAnalysis.setTrafficCompositionRate(sectionData.get("trafficCompositionRate").toString());
            } else {
                sectionTrafficIndexAnalysis.setCrowdingRate(UniversalEnum.ZERO.getValue());
                sectionTrafficIndexAnalysis.setSaturationRate(UniversalEnum.ZERO.getValue());
                sectionTrafficIndexAnalysis.setTrafficCompositionRate(UniversalEnum.ZERO.getValue());
            }

            if (lastYearData.containsKey(sectionName)){
                Map<String, Object> sectionData = lastYearData.get(sectionName).get(UniversalEnum.ZERO.getNumber());
                sectionTrafficIndexAnalysis.setCrowdingRateLastYear(sectionData.get("crowdingRate").toString());
                sectionTrafficIndexAnalysis.setSaturationRateLastYear(sectionData.get("saturationRate").toString());
                sectionTrafficIndexAnalysis.setTrafficCompositionRateLastYear(sectionData.get("trafficCompositionRate").toString());
            } else {
                sectionTrafficIndexAnalysis.setCrowdingRateLastYear(UniversalEnum.ZERO.getValue());
                sectionTrafficIndexAnalysis.setSaturationRateLastYear(UniversalEnum.ZERO.getValue());
                sectionTrafficIndexAnalysis.setTrafficCompositionRateLastYear(UniversalEnum.ZERO.getValue());
            }
            list.add(sectionTrafficIndexAnalysis);

        }

        ExcelUtil<SectionTrafficIndexAnalysis> util = new ExcelUtil<>(SectionTrafficIndexAnalysis.class);
        util.exportExcel(response, list, UniversalEnum.SECTION_TRAFFIC_INDEX_ANALYSIS.getValue());
        // 将查询结果封装为成功响应并返回
    }

    @ApiOperation("通指标时间分布")
    @GetMapping("/history/passIndicatorTimeDistribution")
    public AjaxResult passIndicatorTimeDistribution(String startDate, String direction,String periodType ){
       List<Map<String, Object>>  mapList = dcGantryMetricsStatisticsDataService.passIndicatorTimeDistribution(startDate,direction,periodType);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(mapList);
    }
    @ApiOperation("交通指标雷达图")
    @GetMapping("/history/radarMapOfTrafficIndicators")
    public AjaxResult radarMapOfTrafficIndicators(String startDate, String direction,String periodType ){
      Map<String, Object>  map = dcGantryMetricsStatisticsDataService.radarMapOfTrafficIndicators(startDate,direction,periodType);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(map);
    }
    @ApiOperation("综合指标查询")
    @GetMapping("/history/comprehensiveIndexQuery")
    public TableDataInfo comprehensiveIndexQuery(ComprehensiveIndexQuery comprehensiveIndexQuery){
        startPage();
        List<ComprehensiveIndexQuery>  mapList = dcGantryMetricsStatisticsDataService.comprehensiveIndexQuery(comprehensiveIndexQuery);
        // 将查询结果封装为成功响应并返回
        return getDataTable(mapList);
    }

    @ApiOperation("导出综合指标")
    //@PreAuthorize("@ss.hasPermi('system:event:export')")
    @Log(title = "导出综合指标", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, @RequestBody ComprehensiveIndexQuery comprehensiveIndexQuery)
    {
        List<ComprehensiveIndexQuery>  list = dcGantryMetricsStatisticsDataService.comprehensiveIndexQuery(comprehensiveIndexQuery);
        ExcelUtil<ComprehensiveIndexQuery> util = new ExcelUtil<ComprehensiveIndexQuery>(ComprehensiveIndexQuery.class);
        util.exportExcel(response, list, UniversalEnum.EVENT_INFORMATION_DATA.getValue());
    }

    /**
     * 获取门架指标统计数据
     *
     * @param request 包含查询条件的请求对象,用于筛选历史门架指标统计数据
     * @return 返回一个AjaxResult对象,其中包含了查询到的门架指标统计数据列表
     */
    @ApiOperation("获取门架交通特指数数据")
    @GetMapping("/history/gantry-metrics")
    public AjaxResult historyGantryMetrics(DcGantryMetricsStatisticsData request){
        // 调用服务层方法,根据请求条件查询历史车门架数据
        List<DcGantryMetricsStatisticsData> dcStatisticsData = dcGantryMetricsStatisticsDataService.gantryMetricsData(request);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(dcStatisticsData);
    }

    /********************************************* 智慧高速平接口 **************************************************/


    /**
     * 获取在途车辆流量(分车型)
     * 该接口不接受任何参数,调用后返回在途车辆的统计数据,数据格式为JSONObject。
     *
     * @return AjaxResult 返回类型为AjaxResult,其中包含了操作结果和在途车辆统计数据的JSONObject。
     */
    @ApiOperation("获取在途车辆流量(分车型)")
    @GetMapping("/current/in-transit-vehicles")
    public AjaxResult vehiclesInTransit() throws HttpException, IOException {
        // 调用服务层方法,获取在途车辆的统计数据
        JSONArray dcStatisticsData = dcTrafficStatisticsService.vehiclesInTransit();
        return AjaxResult.success(dcStatisticsData);
    }

    @ApiOperation("获取在途车路段平均车速")
    @GetMapping("/current/average-speed")
    public AjaxResult currentAverageSpeed() throws HttpException, IOException {
        // 调用服务层方法,获取在途车辆的统计数据
        JSONArray dcStatisticsData = dcTrafficStatisticsService.currentAverageSpeed();
        return AjaxResult.success(dcStatisticsData);
    }

    /**
     * 获取当前拥堵事件信息(智慧高速平台)
     *
     * @return 返回一个AjaxResult对象,其中包含了查询结果。如果查询成功,则结果中封装了当前拥堵路段的数据列表。
     */
    @ApiOperation("获取当前拥堵事件信息")
    @GetMapping("/current/event-congested")
    public AjaxResult currentEventCongested() throws HttpException, IOException {
        // 调用服务层方法,获取当前交通指标数据
        JSONArray jsonArray = dcTrafficStatisticsService.currentEventCongested();
        // 将获取到的交通指标数据封装为成功的结果并返回
        return AjaxResult.success(jsonArray);
    }

    /**
     * 获取当前拥堵路段信息
     *
     * @return 返回一个AjaxResult对象,其中包含了查询结果。如果查询成功,则结果中封装了当前拥堵路段的数据列表。
     */
    @ApiOperation("获取当前路段拥堵信息")
    @GetMapping("/current/section-congested")
    public AjaxResult currentSectionCongested() throws HttpException, IOException {
        // 调用服务层方法,获取当前交通指标数据
        List<DcRoadSectionCongestion> roadSectionCongestions = dcTrafficStatisticsService.currentSectionCongested();
        // 将获取到的交通指标数据封装为成功的结果并返回
        return AjaxResult.success(roadSectionCongestions);
    }

    /**
     * 获取车道占有率信息
     *
     */
    @ApiOperation("获取车道占有率信息")
    @GetMapping("/history/lane-occupancy")
    public AjaxResult laneOccupancy(String startDate, String endDate) throws HttpException, IOException {
        // 调用服务层方法,获取当前交通指标数据
        JSONArray jsonArray = dcTrafficStatisticsService.laneOccupancy(startDate, endDate);
        // 将获取到的交通指标数据封装为成功的结果并返回
        return AjaxResult.success(jsonArray);
    }
/**
 * 断面小时车流量分车型
 */
@ApiOperation("断面小时车流量分车型")
@GetMapping("/history/sectionHourlyTrafficFlow")
public AjaxResult sectionHourlyTrafficFlow(String startDate, String endDate) throws HttpException, IOException {
    // 调用服务层方法,获取当前交通指标数据
    JSONArray jsonArray = dcTrafficStatisticsService.sectionHourlyTrafficFlow(startDate, endDate);
    // 将获取到的交通指标数据封装为成功的结果并返回
    return AjaxResult.success(jsonArray);

}/**
 * 各收费站入口分车型车流量
 */
@ApiOperation("各收费站入口分车型小时车流量")
@GetMapping("/history/trafficFlowAtTollStationEntranceHour")
public AjaxResult trafficFlowAtTollStationEntranceHour(String startDate, String endDate,String stationType) throws HttpException, IOException {
    // 调用服务层方法,获取当前交通指标数据
    List<Map<String, String>> jsonArray = dcTrafficStatisticsService.trafficFlowAtTollStationEntrance(startDate, endDate, stationType);
    // 将获取到的交通指标数据封装为成功的结果并返回
    return AjaxResult.success(jsonArray);
}

/**
 * 各收费站入口分车型小时车流量
 */
@ApiOperation("各收费站入口分车型车流量")
@GetMapping("/history/trafficFlowAtTollStationEntrance")
public AjaxResult trafficFlowAtTollStationEntrance(String startDate, String endDate,String stationType) throws HttpException, IOException {
    // 调用服务层方法,获取当前交通指标数据
    JSONArray jsonArray = dcTrafficStatisticsService.trafficFlowAtTollStationEntranceHour(startDate, endDate, stationType);
    // 将获取到的交通指标数据封装为成功的结果并返回
    return AjaxResult.success(jsonArray);

}
    /**
     * 全路段双向实时车流量
     */
    @ApiOperation("全路段双向实时车流量")
    @GetMapping("/history/realTimeTrafficFlowHour")
    public AjaxResult realTimeTrafficFlowHour() throws HttpException, IOException{
        Map<String,List<Map<String, Object>>> mapList = dcTrafficStatisticsService.realTimeTrafficFlowHour();
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(mapList);
    }
    @ApiOperation("按照桩号查询门架数据 ")
    @GetMapping("/history/queryTheGantryDataByPileNumber")
    public AjaxResult queryTheGantryDataByPileNumber(String startDate,String stakeMark) throws HttpException, IOException{
        List<Map<String,Object>> mapList = dcTrafficStatisticsService.queryTheGantryDataByPileNumber(startDate,stakeMark);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(mapList);
    }
    /**
     * 获取据库中 收费站统计数据
     * @param startDate 时间
     * @param accessType 出入口 1入  2出
     * @param periodType 方向
     */
    @ApiOperation("获取据库中收费站数数据")
    @GetMapping("/history/TollBoothStatistics")
    public AjaxResult TollBoothStatistics(String startDate,String accessType,String periodType) throws HttpException, IOException{
        List<Map<String, String>> mapList = dcTollStationStatisticsDataService.TollBoothStatistics(startDate,accessType,periodType);
        // 将查询结果封装为成功响应并返回
        return AjaxResult.success(mapList);
    }

    /**
     * 导出全路段双向实时车流量
     */
    @ApiOperation(value = "导出全路段双向实时车流量",tags = {"ECharts导出"})
    @GetMapping("/history/exportRealTimeTrafficFlowHour")
    public void exportRealTimeTrafficFlowHour(HttpServletResponse response) throws IOException, HttpException {

        response.setContentType(UniversalEnum.DERIVE_THE_TWO_WAY_REAL_TIME_TRAFFIC_FLOW_OF_THE_WHOLE_SECTION.getValue());
        response.setCharacterEncoding(UniversalEnum.LOWERCASE_UTF_8.getValue());
        String fileName = UniversalEnum.REAL_TIME_TRAFFIC_FLOW_IN_BOTH_DIRECTIONS_XLSX.name();
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);


        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(UniversalEnum.TIME_FORMAT_YEARS_MONTH_DAY.getValue());
        LocalDate currentDate = LocalDate.now();
        String now = currentDate.format(formatter);

        // 获取一年前的日期
        LocalDate oneYearAgo = currentDate.minusYears(UniversalEnum.ONE.getNumber());
        String lastYear = oneYearAgo.format(formatter);

        Map<String,List<Map<String,Object>>> map = dcTrafficStatisticsService.realTimeTrafficFlowHour();
        if (map != null){
            List<Map<String,Object>> thisYearHZ = map.get(UniversalEnum.ONE.getValue());
            List<Map<String,Object>> thisYearJN = map.get(UniversalEnum.TWO.getValue());
            List<Map<String,Object>> lastYearHZ = map.get(UniversalEnum.THREE.getValue());
            List<Map<String,Object>> lastYearJN = map.get(UniversalEnum.FOUR.getValue());

            XSSFWorkbook workbook = new XSSFWorkbook(); // 创建工作簿
            Sheet sheet = workbook.createSheet(UniversalEnum.THE_WHOLE_SECTION_TWO_WAY_REAL_TIME_TRAFFIC_FLOW.getValue()); // 创建工作表

            // 创建数据行样式
            CellStyle dataStyle = workbook.createCellStyle();
            dataStyle.setAlignment(HorizontalAlignment.CENTER);
            dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            dataStyle.setBorderRight(BorderStyle.THIN);
            dataStyle.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            dataStyle.setBorderLeft(BorderStyle.THIN);
            dataStyle.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            dataStyle.setBorderTop(BorderStyle.THIN);
            dataStyle.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            dataStyle.setBorderBottom(BorderStyle.THIN);
            dataStyle.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            Font dataFont = workbook.createFont();
            dataFont.setFontName(UniversalEnum.ARIAL.getValue());
            dataFont.setFontHeightInPoints((short) UniversalEnum.TEN.getNumber());
            dataStyle.setFont(dataFont);

            // 创建表头样式
            CellStyle headerStyle = workbook.createCellStyle();
            headerStyle.cloneStyleFrom(dataStyle);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            headerStyle.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font headerFont = workbook.createFont();
            headerFont.setFontName(UniversalEnum.ARIAL.getValue());
            headerFont.setFontHeightInPoints((short) UniversalEnum.TEN.getNumber());
            headerFont.setBold(true);
            headerFont.setColor(IndexedColors.WHITE.getIndex());
            headerStyle.setFont(headerFont);

            // 添加第一层级表头
            Row row = sheet.createRow(UniversalEnum.ZERO.getNumber());
            Cell cell = row.createCell(UniversalEnum.ZERO.getNumber());
            cell.setCellValue(UniversalEnum.ROAD_SECTION_NAME.getValue());
            cell.setCellStyle(headerStyle);
            cell = row.createCell(UniversalEnum.ONE.getNumber());
            cell.setCellValue(UniversalEnum.DIRECTION_OF_JINAN.getValue());
            cell.setCellStyle(headerStyle);
            cell = row.createCell(UniversalEnum.TWO.getNumber());
            cell.setCellValue(UniversalEnum.EMPTY_STRING.getValue());
            cell.setCellStyle(headerStyle);;
            cell = row.createCell(UniversalEnum.THREE.getNumber());
            cell.setCellValue(UniversalEnum.DIRECTION_OF_HEZE.getValue());
            cell.setCellStyle(headerStyle);
            cell = row.createCell(UniversalEnum.FOUR.getNumber());
            cell.setCellValue(UniversalEnum.EMPTY_STRING.getValue());
            cell.setCellStyle(headerStyle);

            // 添加第二层级表头(与第一层级对齐)
            Row subHeaderRow1 = sheet.createRow(UniversalEnum.ONE.getNumber());
            cell = subHeaderRow1.createCell(UniversalEnum.ZERO.getNumber());
            cell.setCellValue(UniversalEnum.EMPTY_STRING.getValue());
            cell.setCellStyle(headerStyle);
            cell = subHeaderRow1.createCell(UniversalEnum.ONE.getNumber());
            cell.setCellValue(UniversalEnum.CURRENT_TRAFFIC_FLOW.getValue());
            cell.setCellStyle(headerStyle);

            cell = subHeaderRow1.createCell(UniversalEnum.TWO.getNumber());
            cell.setCellValue(UniversalEnum.THE_SAME_PERIOD_LAST_YEAR.getValue());
            cell.setCellStyle(headerStyle);
            cell = subHeaderRow1.createCell(UniversalEnum.THREE.getNumber());
            cell.setCellValue(UniversalEnum.CURRENT_TRAFFIC_FLOW.getValue());
            cell.setCellStyle(headerStyle);

            cell = subHeaderRow1.createCell(UniversalEnum.FOUR.getNumber());
            cell.setCellValue(UniversalEnum.THE_SAME_PERIOD_LAST_YEAR.getValue());
            cell.setCellStyle(headerStyle);

            //合并单元格,参数依次为起始行,结束行,起始列,结束列 (从0开始)
            //路段名称
            sheet.addMergedRegion(new CellRangeAddress(UniversalEnum.ZERO.getNumber(), UniversalEnum.ONE.getNumber(), UniversalEnum.ZERO.getNumber(), UniversalEnum.ZERO.getNumber()));
            //济南方向
            sheet.addMergedRegion(new CellRangeAddress(UniversalEnum.ZERO.getNumber(), UniversalEnum.ZERO.getNumber(), UniversalEnum.ONE.getNumber(), UniversalEnum.TWO.getNumber()));
            //菏泽方向
            sheet.addMergedRegion(new CellRangeAddress(UniversalEnum.ZERO.getNumber(), UniversalEnum.ZERO.getNumber(), UniversalEnum.THREE.getNumber(), UniversalEnum.FOUR.getNumber()));

            for (int i = UniversalEnum.ZERO.getNumber(); i < thisYearHZ.size(); i++) {
                Row subHeaderRow = sheet.createRow(i+UniversalEnum.TWO.getNumber());
                cell = subHeaderRow.createCell(UniversalEnum.ZERO.getNumber());
                cell.setCellValue(thisYearJN.get(i).get("name").toString());
                cell.setCellStyle(dataStyle);
                cell = subHeaderRow.createCell(UniversalEnum.ONE.getNumber());
                cell.setCellValue(thisYearJN.get(i).get("totalFlow").toString());
                cell.setCellStyle(dataStyle);
                cell = subHeaderRow.createCell(UniversalEnum.TWO.getNumber());
                cell.setCellValue(lastYearJN.get(i).get("totalFlow").toString());
                cell.setCellStyle(dataStyle);
                cell = subHeaderRow.createCell(UniversalEnum.THREE.getNumber());
                cell.setCellValue(thisYearHZ.get(i).get("totalFlow").toString());
                cell.setCellStyle(dataStyle);
                cell = subHeaderRow.createCell(UniversalEnum.FOUR.getNumber());
                cell.setCellValue(lastYearHZ.get(i).get("totalFlow").toString());
                cell.setCellStyle(dataStyle);
            }


            // 写入文件
            try (ServletOutputStream outputStream = response.getOutputStream()){
                workbook.write(outputStream);
            } finally {
                workbook.close();
            }

        }

    }

}