package com.sundot.airport.web.controller.quality;

import com.sundot.airport.attendance.calculator.AttendancePersonCountCalculator;
import com.sundot.airport.attendance.calculator.BrigadeAttendancePersonCountCalculator;
import com.sundot.airport.attendance.dto.AttendanceTrendDataDTO;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.attendance.dto.AttendancePersonStatsDTO;
import com.sundot.airport.common.enums.DeptTypeEnum;
import com.sundot.airport.common.statistics.*;
import com.sundot.airport.common.utils.DeptUtils;
import com.sundot.airport.common.utils.StringUtils;
import com.sundot.airport.system.service.ISysDeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.sundot.airport.common.utils.SecurityUtils.getDeptId;

/**
 * 出勤人次控制器
 * 根据时间维度返回总体+大队的人次数据
 */
@Api(tags = "出勤人次")
@RestController
@RequestMapping("/quality/attendance")
public class SimpleAttendancePersonController {

    @Autowired
    private AttendancePersonCountCalculator overallCalculator; // 全站计算器

    @Autowired
    private BrigadeAttendancePersonCountCalculator deptCalculator; // 大队计算器

    @Autowired
    private MultiModelIndicatorCalculator multiModelIndicatorCalculator;

    @Autowired
    private ISysDeptService deptService;


    /**
     * 出勤人次分析
     * 支持按大队ID、科室ID、班组ID、用户ID 进行统计
     */
    @ApiOperation("出勤人次分析")
    @PostMapping("/calculate")
    public List<AttendancePersonStatsDTO> calculateStatistics(@RequestBody IndicatorCalculationParams params) {
        List<AttendancePersonStatsDTO> results = new ArrayList<>();

        if (params.getDeptId() != null || params.getUserId() != null) {
            // 传入了部门 ID 或用户 ID，直接统计
            results.add(createAttendancePersonStatsForParams(params));
        } else {
            // 未传入具体 ID，默认获取当前用户所在站点下的科室
            Long topSiteId = DeptUtils.getTopSiteId(deptService.selectDeptById(getDeptId()));
            List<SysDept> brigadeUnderSite = getBrigadesUnderSite(topSiteId);
            brigadeUnderSite.add(deptService.selectDeptById(topSiteId));
            brigadeUnderSite.forEach(dept -> {
                results.add(createAttendancePersonStats(dept, params));
            });
        }

        return results;
    }

    /**
     * 出勤人次趋势数据
     * 根据时间维度参数动态生成柱状图数据
     * 支持月度（同比+环比）、季度（同比）、年度（同比）等多种展示方式
     *
     * @param params 时间维度参数（年、季度、月等）
     * @return 趋势数据列表
     */
    @ApiOperation("出勤人次趋势数据")
    @PostMapping("/trend-data")
    public List<AttendanceTrendDataDTO> getTrendData(@RequestBody IndicatorCalculationParams params) {
        // 根据传入参数决定统计策略
        if (params.getDeptId() != null || params.getUserId() != null) {
            // 传入了部门 ID 或用户 ID，返回简化版的趋势数据
            return getSimpleTrendData(params);
        }

        // 默认按站点 + 三科模式统计
        List<AttendanceTrendDataDTO> results = new ArrayList<>();

        // 根据时间维度类型决定展示策略
        if (params.getMonth() != null) {
            // 月度：展示当前月、上月、去年同期（同比+环比）
            results.addAll(generateMonthlyTrendData(params));
        } else if (params.getQuarter() != null) {
            // 季度：展示当前季度和去年同期
            results.addAll(generateQuarterlyTrendData(params));
        } else if (params.getYear() != null) {
            // 年度：仅展示当前年和去年（仅同比）
            results.addAll(generateYearlyTrendData(params));
        } else {
            // 默认按月度处理
            results.addAll(generateMonthlyTrendData(params));
        }

        return results;
    }

    /**
     * 趋势数据（用于指定部门/个人的场景）
     * 仅返回单条数据序列
     */
    private List<AttendanceTrendDataDTO> getSimpleTrendData(IndicatorCalculationParams params) {
        List<AttendanceTrendDataDTO> results = new ArrayList<>();

        // 根据时间维度类型决定展示策略
        if (params.getMonth() != null) {
            // 月度：展示当前月、上月、去年同期
            results.addAll(generateSimpleMonthlyTrendData(params));
        } else if (params.getQuarter() != null) {
            // 季度：展示当前季度和去年同期
            results.addAll(generateSimpleQuarterlyTrendData(params));
        } else if (params.getYear() != null) {
            // 年度：仅展示当前年和去年
            results.addAll(generateSimpleYearlyTrendData(params));
        } else {
            // 默认按月度处理
            results.addAll(generateSimpleMonthlyTrendData(params));
        }

        return results;
    }

    /**
     * 月度趋势数据
     */
    private List<AttendanceTrendDataDTO> generateSimpleMonthlyTrendData(IndicatorCalculationParams params) {
        List<AttendanceTrendDataDTO> results = new ArrayList<>();

        // 计算当前月数据
        AttendancePersonStatsDTO currentData = createAttendancePersonStatsForParams(params);

        // 计算上月数据
        IndicatorCalculationParams lastMonthParams = createLastMonthParams(params);
        AttendancePersonStatsDTO lastMonthData = createAttendancePersonStatsForParams(lastMonthParams);

        // 计算去年同期数据
        IndicatorCalculationParams lastYearParams = createLastYearParams(params);
        AttendancePersonStatsDTO lastYearData = createAttendancePersonStatsForParams(lastYearParams);

        // 构造趋势数据点
        results.add(createSimpleTrendDataPoint(getLastYearMonthLabel(params), lastYearData));
        results.add(createSimpleTrendDataPoint(getLastMonthLabel(params), lastMonthData));
        results.add(createSimpleTrendDataPoint(getMonthLabel(params), currentData));

        return results;
    }

    /**
     * 季度趋势数据
     */
    private List<AttendanceTrendDataDTO> generateSimpleQuarterlyTrendData(IndicatorCalculationParams params) {
        List<AttendanceTrendDataDTO> results = new ArrayList<>();

        // 计算当前季度数据
        AttendancePersonStatsDTO currentData = createAttendancePersonStatsForParams(params);

        // 计算上季度数据
        IndicatorCalculationParams lastQuarterParams = createLastQuarterParams(params);
        AttendancePersonStatsDTO lastQuarterData = createAttendancePersonStatsForParams(lastQuarterParams);

        // 计算去年同期季度数据
        IndicatorCalculationParams lastYearParams = createLastYearParams(params);
        AttendancePersonStatsDTO lastYearData = createAttendancePersonStatsForParams(lastYearParams);

        // 构造趋势数据点
        results.add(createSimpleTrendDataPoint(getLastYearQuarterLabel(params), lastYearData));
        results.add(createSimpleTrendDataPoint(getLastQuarterLabel(params), lastQuarterData));
        results.add(createSimpleTrendDataPoint(getQuarterLabel(params), currentData));

        return results;
    }

    /**
     * 年度趋势数据
     */
    private List<AttendanceTrendDataDTO> generateSimpleYearlyTrendData(IndicatorCalculationParams params) {
        List<AttendanceTrendDataDTO> results = new ArrayList<>();

        // 计算当前年数据
        AttendancePersonStatsDTO currentData = createAttendancePersonStatsForParams(params);

        // 计算去年数据
        IndicatorCalculationParams lastYearParams = createLastYearParams(params);
        AttendancePersonStatsDTO lastYearData = createAttendancePersonStatsForParams(lastYearParams);

        // 构造趋势数据点
        results.add(createSimpleTrendDataPoint((params.getYear() - 1) + "年", lastYearData));
        results.add(createSimpleTrendDataPoint(params.getYear() + "年", currentData));

        return results;
    }

    /**
     * 趋势数据点
     */
    private AttendanceTrendDataDTO createSimpleTrendDataPoint(String timeLabel, AttendancePersonStatsDTO stats) {
        AttendanceTrendDataDTO data = new AttendanceTrendDataDTO();
        data.setTimeLabel(timeLabel);
        // 将单个统计值设置为 overall 字段
        data.setOverall(stats.getCurrentValue() != null ? stats.getCurrentValue() : BigDecimal.ZERO);
        return data;
    }

    /**
     * 生成月度趋势数据（同比+环比）
     * 展示：当前月、上月、去年同期
     */
    private List<AttendanceTrendDataDTO> generateMonthlyTrendData(IndicatorCalculationParams params) {
        List<AttendanceTrendDataDTO> results = new ArrayList<>();

        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(deptService.selectDeptById(getDeptId()));
        List<SysDept> stationAndThreeDepts = getBrigadesUnderSite(topSiteId);
        stationAndThreeDepts.add(deptService.selectDeptById(topSiteId));


        // 计算当前月数据
        List<AttendancePersonStatsDTO> currentList = calculateDeptStats(stationAndThreeDepts, params);

        // 计算上月数据
        IndicatorCalculationParams lastMonthParams = createLastMonthParams(params);
        List<AttendancePersonStatsDTO> lastMonthList = calculateDeptStats(stationAndThreeDepts, lastMonthParams);

        // 计算去年同期数据
        IndicatorCalculationParams lastYearParams = createLastYearParams(params);
        List<AttendancePersonStatsDTO> lastYearList = calculateDeptStats(stationAndThreeDepts, lastYearParams);


        // 构造柱状图数据
        AttendanceTrendDataDTO currentData = createTrendDataPoint(getMonthLabel(params), currentList);
        AttendanceTrendDataDTO lastMonthData = createTrendDataPoint(getLastMonthLabel(params), lastMonthList);
        AttendanceTrendDataDTO lastYearData = createTrendDataPoint(getLastYearMonthLabel(params), lastYearList);

        results.add(lastYearData);
        results.add(lastMonthData);
        results.add(currentData);

        return results;
    }

    /**
     * 生成季度趋势数据（同比+环比）
     * 展示：当前季度、上季度、去年同期季度
     */
    private List<AttendanceTrendDataDTO> generateQuarterlyTrendData(IndicatorCalculationParams params) {
        List<AttendanceTrendDataDTO> results = new ArrayList<>();
        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(deptService.selectDeptById(getDeptId()));
        List<SysDept> stationAndThreeDepts = getBrigadesUnderSite(topSiteId);
        stationAndThreeDepts.add(deptService.selectDeptById(topSiteId));
        // 计算当前季度数据
        List<AttendancePersonStatsDTO> currentList = calculateDeptStats(stationAndThreeDepts, params);

        // 计算上季度数据
        IndicatorCalculationParams lastQuarterParams = createLastQuarterParams(params);
        List<AttendancePersonStatsDTO> lastQuarterList = calculateDeptStats(stationAndThreeDepts, lastQuarterParams);

        // 计算去年同期季度数据
        IndicatorCalculationParams lastYearParams = createLastYearParams(params);
        List<AttendancePersonStatsDTO> lastYearList = calculateDeptStats(stationAndThreeDepts, lastYearParams);

        // 构造柱状图数据
        AttendanceTrendDataDTO currentData = createTrendDataPoint(getQuarterLabel(params), currentList);
        AttendanceTrendDataDTO lastQuarterData = createTrendDataPoint(getLastQuarterLabel(params), lastQuarterList);
        AttendanceTrendDataDTO lastYearData = createTrendDataPoint(getLastYearQuarterLabel(params), lastYearList);

        results.add(lastYearData);
        results.add(lastQuarterData);
        results.add(currentData);
        return results;
    }

    /**
     * 生成年度趋势数据（仅同比）
     * 展示：当前年、去年
     */
    private List<AttendanceTrendDataDTO> generateYearlyTrendData(IndicatorCalculationParams params) {
        List<AttendanceTrendDataDTO> results = new ArrayList<>();
        // 获取当前用户所在站点ID
        Long topSiteId = DeptUtils.getTopSiteId(deptService.selectDeptById(getDeptId()));
        List<SysDept> stationAndThreeDepts = getBrigadesUnderSite(topSiteId);
        stationAndThreeDepts.add(deptService.selectDeptById(topSiteId));
        // 计算当前年数据
        List<AttendancePersonStatsDTO> currentList = calculateDeptStats(stationAndThreeDepts, params);

        // 计算去年数据
        IndicatorCalculationParams lastYearParams = createLastYearParams(params);
        List<AttendancePersonStatsDTO> lastYearList = calculateDeptStats(stationAndThreeDepts, lastYearParams);

        // 构造柱状图数据
        AttendanceTrendDataDTO currentData = createTrendDataPoint(params.getYear() + "年", currentList);
        AttendanceTrendDataDTO lastYearData = createTrendDataPoint((params.getYear() - 1) + "年", lastYearList);
        results.add(lastYearData);
        results.add(currentData);


        return results;
    }

    /**
     * 计算部门统计数据
     */
    private List<AttendancePersonStatsDTO> calculateDeptStats(List<SysDept> depts, IndicatorCalculationParams params) {
        List<AttendancePersonStatsDTO> results = new ArrayList<>();
        depts.forEach(dept -> {
            results.add(createAttendancePersonStats(dept, params));
        });
        return results;
    }

    /**
     * 创建趋势数据点
     */
    private AttendanceTrendDataDTO createTrendDataPoint(String timeLabel, List<AttendancePersonStatsDTO> dataList) {
        AttendanceTrendDataDTO data = new AttendanceTrendDataDTO();
        data.setTimeLabel(timeLabel);
        data.setOverall(getStationValue(dataList));
        data.setData1(getDeptValue(dataList, "安检一大队"));
        data.setData2(getDeptValue(dataList, "安检二大队"));
        data.setData3(getDeptValue(dataList, "安检三大队"));
        data.setData4(getDeptValue(dataList, "安检综合大队"));
        return data;
    }

    /**
     * 获取季度标签
     */
    private String getQuarterLabel(IndicatorCalculationParams params) {
        if (params.getYear() != null && params.getQuarter() != null) {
            return params.getYear() + "年第" + params.getQuarter() + "季度";
        }
        return "当前季度";
    }

    /**
     * 获取上季度标签
     */
    private String getLastQuarterLabel(IndicatorCalculationParams params) {
        if (params.getYear() != null && params.getQuarter() != null) {
            int lastQuarter = params.getQuarter() - 1;
            int year = params.getYear();
            if (lastQuarter <= 0) {
                lastQuarter = 4;
                year = year - 1;
            }
            return year + "年第" + lastQuarter + "季度";
        }
        return "上季度";
    }

    /**
     * 获取去年季度标签
     */
    private String getLastYearQuarterLabel(IndicatorCalculationParams params) {
        if (params.getYear() != null && params.getQuarter() != null) {
            return (params.getYear() - 1) + "年第" + params.getQuarter() + "季度";
        }
        return "去年同期季度";
    }

    /**
     * 月度标签
     */
    private String getMonthLabel(IndicatorCalculationParams params) {
        if (params.getYear() != null && params.getMonth() != null) {
            return params.getYear() + "年" + params.getMonth() + "月";
        }
        return "当前月度";
    }

    /**
     * 获取上月标签
     */
    private String getLastMonthLabel(IndicatorCalculationParams params) {
        if (params.getYear() != null && params.getMonth() != null) {
            int lastMonth = params.getMonth() - 1;
            int year = params.getYear();
            if (lastMonth <= 0) {
                lastMonth = 12;
                year = year - 1;
            }
            return year + "年" + lastMonth + "月";
        }
        return "上月";
    }

    /**
     * 获取去年本月度标签
     */
    private String getLastYearMonthLabel(IndicatorCalculationParams params) {
        if (params.getYear() != null && params.getMonth() != null) {
            return (params.getYear() - 1) + "年" + params.getMonth() + "月";
        }
        return "去年同期月度";
    }


    /**
     * 创建出勤人次统计对象（根据部门实体）
     */
    private AttendancePersonStatsDTO createAttendancePersonStats(SysDept sysDept, IndicatorCalculationParams params) {
        AttendancePersonStatsDTO result = new AttendancePersonStatsDTO();
        result.setDeptId(sysDept.getDeptId());
        result.setDeptName(sysDept.getDeptName());
        result.setDeptType(sysDept.getDeptType());
        try {
            IndicatorCalculationParams calcParams = new IndicatorCalculationParams();
            calcParams.setDeptId(sysDept.getDeptId());
            calcParams.setYear(params.getYear());
            calcParams.setQuarter(params.getQuarter());
            calcParams.setMonth(params.getMonth());
            calcParams.setStartTime(params.getStartTime());
            calcParams.setEndTime(params.getEndTime());
            calcParams.setChainRatio(params.getChainRatio());
            calcParams.setYearOnYear(params.getYearOnYear());

            IndicatorCalculationResult currentResult;
            if (sysDept.getDeptType().equals(DeptTypeEnum.STATION.getCode())) {
                currentResult = multiModelIndicatorCalculator.calculateWithRatio(overallCalculator, calcParams);
            } else {
                currentResult = multiModelIndicatorCalculator.calculateWithRatio(deptCalculator, calcParams);
            }

            if ("SUCCESS".equals(currentResult.getStatus())) {
                result.setCurrentValue(currentResult.getValue());
                result.setBaselineValue(currentResult.getBaselineValue());

                boolean showChainRatio = params.getChainRatio() != null && params.getChainRatio();
                boolean showYearOnYear = params.getYearOnYear() != null && params.getYearOnYear();

                if (params.getYear() != null && params.getQuarter() == null && params.getMonth() == null) {
                    showChainRatio = false;
                }

                if (showYearOnYear && currentResult.getYearOnYearValue() != null) {
                    result.setYearOnYearValue(currentResult.getYearOnYearValue());
                    result.setYearOnYearDirection(getDirectionText(currentResult.getYearOnYearValue()));
                    result.setYearOnYearTimeDimension((TimeDimensionParams) currentResult.getExtraInfo().get("yearOnYear"));
                }

                if (showChainRatio && currentResult.getChainRatioValue() != null) {
                    result.setChainRatioValue(currentResult.getChainRatioValue());
                    result.setChainRatioDirection(getDirectionText(currentResult.getChainRatioValue()));
                    result.setChainTimeDimension((TimeDimensionParams) currentResult.getExtraInfo().get("chain"));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    /**
     * 创建出勤人次统计对象（根据参数直接计算）
     * 支持按部门、班组、个人进行统计
     */
    private AttendancePersonStatsDTO createAttendancePersonStatsForParams(IndicatorCalculationParams params) {
        AttendancePersonStatsDTO result = new AttendancePersonStatsDTO();

        // 设置部门信息
        if (params.getDeptId() != null) {
            SysDept dept = deptService.selectDeptById(params.getDeptId());
            if (dept != null) {
                result.setDeptId(dept.getDeptId());
                result.setDeptName(dept.getDeptName());
                result.setDeptType(dept.getDeptType());
            }
        }

        try {
            IndicatorCalculationResult currentResult = multiModelIndicatorCalculator.calculateWithRatio(deptCalculator, params);

            if ("SUCCESS".equals(currentResult.getStatus())) {
                result.setCurrentValue(currentResult.getValue());
                result.setBaselineValue(currentResult.getBaselineValue());

                boolean showChainRatio = params.getChainRatio() != null && params.getChainRatio();
                boolean showYearOnYear = params.getYearOnYear() != null && params.getYearOnYear();

                if (params.getYear() != null && params.getQuarter() == null && params.getMonth() == null) {
                    showChainRatio = false;
                }

                if (showYearOnYear && currentResult.getYearOnYearValue() != null) {
                    result.setYearOnYearValue(currentResult.getYearOnYearValue());
                    result.setYearOnYearDirection(getDirectionText(currentResult.getYearOnYearValue()));
                    result.setYearOnYearTimeDimension((TimeDimensionParams) currentResult.getExtraInfo().get("yearOnYear"));
                }

                if (showChainRatio && currentResult.getChainRatioValue() != null) {
                    result.setChainRatioValue(currentResult.getChainRatioValue());
                    result.setChainRatioDirection(getDirectionText(currentResult.getChainRatioValue()));
                    result.setChainTimeDimension((TimeDimensionParams) currentResult.getExtraInfo().get("chain"));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    /**
     * 创建上月参数
     */
    private IndicatorCalculationParams createLastMonthParams(IndicatorCalculationParams originalParams) {
        IndicatorCalculationParams params = new IndicatorCalculationParams();
        params.setYear(originalParams.getYear());
        params.setQuarter(originalParams.getQuarter());
        params.setMonth(originalParams.getMonth());
        params.setStartTime(originalParams.getStartTime());
        params.setEndTime(originalParams.getEndTime());
        params.setUserId(originalParams.getUserId());
        params.setDeptId(originalParams.getDeptId());
        params.setChainRatio(false);
        params.setYearOnYear(false);

        // 计算上月
        if (params.getMonth() != null) {
            int lastMonth = params.getMonth() - 1;
            int year = params.getYear();
            if (lastMonth <= 0) {
                lastMonth = 12;
                year = year - 1;
            }
            params.setMonth(lastMonth);
            params.setYear(year);
        }

        return params;
    }

    /**
     * 创建上季度参数
     */
    private IndicatorCalculationParams createLastQuarterParams(IndicatorCalculationParams originalParams) {
        IndicatorCalculationParams params = new IndicatorCalculationParams();
        params.setYear(originalParams.getYear());
        params.setQuarter(originalParams.getQuarter());
        params.setMonth(originalParams.getMonth());
        params.setStartTime(originalParams.getStartTime());
        params.setEndTime(originalParams.getEndTime());
        params.setUserId(originalParams.getUserId());
        params.setDeptId(originalParams.getDeptId());
        params.setChainRatio(false);
        params.setYearOnYear(false);

        // 计算上季度
        if (params.getQuarter() != null) {
            int lastQuarter = params.getQuarter() - 1;
            int year = params.getYear();
            if (lastQuarter <= 0) {
                lastQuarter = 4;
                year = year - 1;
            }
            params.setQuarter(lastQuarter);
            params.setYear(year);
        }

        return params;
    }


    /**
     * 创建去年同期参数
     */
    private IndicatorCalculationParams createLastYearParams(IndicatorCalculationParams originalParams) {
        IndicatorCalculationParams params = new IndicatorCalculationParams();
        params.setYear(originalParams.getYear());
        params.setQuarter(originalParams.getQuarter());
        params.setMonth(originalParams.getMonth());
        params.setStartTime(originalParams.getStartTime());
        params.setEndTime(originalParams.getEndTime());
        params.setUserId(originalParams.getUserId());
        params.setDeptId(originalParams.getDeptId());
        params.setChainRatio(false);
        params.setYearOnYear(false);

        // 计算去年同期
        if (params.getYear() != null) {
            params.setYear(params.getYear() - 1);
        }

        return params;
    }

    /**
     * 获取站点值
     */
    private BigDecimal getStationValue(List<AttendancePersonStatsDTO> list) {
        return list.stream()
                .filter(dto -> DeptTypeEnum.STATION.getCode().equals(dto.getDeptType()))
                .findFirst()
                .map(AttendancePersonStatsDTO::getCurrentValue)
                .orElse(BigDecimal.ZERO);
    }

    /**
     * 获取指定大队的值
     */
    private BigDecimal getDeptValue(List<AttendancePersonStatsDTO> list, String deptName) {
        return list.stream()
                .filter(dto -> DeptTypeEnum.BRIGADE.getCode().equals(dto.getDeptType())
                        && deptName.equals(dto.getDeptName()))
                .findFirst()
                .map(AttendancePersonStatsDTO::getCurrentValue)
                .orElse(BigDecimal.ZERO);
    }

    /**
     * 获取方向文本：上升 或 下降
     */
    private String getDirectionText(String growthRate) {
        if (StringUtils.isEmpty(growthRate)) return "";
        if (growthRate.equals("--")) return "上升";
        return new BigDecimal(growthRate).compareTo(BigDecimal.ZERO) >= 0 ? "上升" : "下降";
    }


    /**
     * 获取站点下的所有大队
     */
    private List<SysDept> getBrigadesUnderSite(Long siteId) {
        List<SysDept> children = deptService.selectChildrenDeptById(siteId);
        return children.stream()
                .filter(dept -> DeptTypeEnum.BRIGADE.getCode().equals(dept.getDeptType()))
                .collect(Collectors.toList());
    }

}