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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysRole;
import com.sundot.airport.common.core.domain.model.LoginUser;
import com.sundot.airport.common.enums.RoleTypeEnum;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.exam.common.HttpResult;
import com.sundot.airport.exam.domain.DailyTask;
import com.sundot.airport.exam.mapper.DailyTaskMapper;
import com.sundot.airport.system.mapper.SysDeptMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Date;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 抽问抽答完成趋势对比接口（PC管理端，美兰4级架构）
 * STATION（安检站）> BRIGADE（大队）> MANAGER（主管）> 班组
 *
 * xAxis 为周期标签，每条 series 的 data 为各周期聚合完成数：
 *   YEAR    → [去年总数, 当年总数]               xAxis: ["2025年","2026年"]
 *   QUARTER → [去年同季度, 上季度, 当季度]        xAxis: ["2025年第1季度","2025年第4季度","2026年第1季度"]
 *   MONTH   → [去年同月, 上月, 当月]              xAxis: ["2025年3月","2026年2月","2026年3月"]
 *
 * 同比 yoyRate   = (当期 - 去年同期) / 去年同期 × 100
 * 环比 chainRatio = (当期 - 上期)   / 上期     × 100（仅 QUARTER/MONTH）
 */
@RestController
@RequestMapping("/v1/cs/app/daily-exam")
public class DailyExamComparisonController {

    private static final Logger log = LoggerFactory.getLogger(DailyExamComparisonController.class);

    private static final String[] QUARTER_NAMES = {"第一", "第二", "第三", "第四"};

    @Autowired
    private DailyTaskMapper dailyTaskMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    /**
     * 抽问抽答完成趋势对比
     *
     * @param dateRangeQueryType 时间类型：YEAR/QUARTER/MONTH，默认 MONTH
     * @param year               年份，默认当前年
     * @param quarter            季度 1-4，dateRangeQueryType=QUARTER 时有效
     * @param month              月份 1-12，dateRangeQueryType=MONTH 时有效
     * @param scopeType          统计范围：STATION/BRIGADE/MANAGER/TEAM/USER，不传则按登录角色自动判断
     * @param scopeId            统计范围ID（deptId 或 userId）
     */
    @GetMapping("/completion-comparison")
    public HttpResult<Map<String, Object>> getCompletionComparison(
            @RequestParam(required = false, defaultValue = "MONTH") String dateRangeQueryType,
            @RequestParam(required = false) Integer year,
            @RequestParam(required = false) Integer quarter,
            @RequestParam(required = false) Integer month,
            @RequestParam(required = false) String scopeType,
            @RequestParam(required = false) Long scopeId) {

        try {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            List<String> roleKeys = loginUser.getUser().getRoles().stream()
                    .map(SysRole::getRoleKey).collect(Collectors.toList());
            Long userDeptId = loginUser.getDeptId();
            Long userId = loginUser.getUserId();

            boolean isStation = userId == 1L
                    || roleKeys.contains(RoleTypeEnum.admin.getCode())
                    || roleKeys.contains(RoleTypeEnum.test.getCode())
                    || roleKeys.contains(RoleTypeEnum.zhijianke.getCode());
            boolean isBrigade = !isStation && (roleKeys.contains(RoleTypeEnum.jingli.getCode())
                    || roleKeys.contains(RoleTypeEnum.xingzheng.getCode()));
            boolean isManager = !isStation && !isBrigade && roleKeys.contains(RoleTypeEnum.kezhang.getCode());

            if (scopeType == null && !isStation && !isBrigade && !isManager) {
                Map<String, Object> noShow = new HashMap<>();
                noShow.put("show", false);
                return HttpResult.success(noShow);
            }

            LocalDate today = LocalDate.now();
            int curYear = (year != null) ? year : today.getYear();
            int curQuarter = (quarter != null) ? quarter : ((today.getMonthValue() - 1) / 3 + 1);
            int curMonth = (month != null) ? month : today.getMonthValue();

            List<String> xAxis = buildXAxisLabels(dateRangeQueryType, curYear, curQuarter, curMonth);
            List<LocalDate[]> periods = buildPeriods(dateRangeQueryType, curYear, curQuarter, curMonth);
            boolean hasChain = !"YEAR".equals(dateRangeQueryType);

            List<Map<String, Object>> series = buildSeries(
                    scopeType, scopeId, xAxis, periods, hasChain,
                    isStation, isBrigade, isManager, userDeptId, loginUser);

            Map<String, Object> result = new LinkedHashMap<>();
            result.put("show", true);
            result.put("xAxis", xAxis);
            result.put("series", series);
            return HttpResult.success(result);

        } catch (Exception e) {
            log.error("获取抽问抽答完成趋势对比失败", e);
            return HttpResult.error("获取完成趋势对比失败：" + e.getMessage());
        }
    }

    // -------------------------------------------------------------------------
    // xAxis 标签
    // -------------------------------------------------------------------------

    /**
     * YEAR    → ["2025年", "2026年"]
     * QUARTER → ["2025年第1季度", "2025年第4季度", "2026年第1季度"]
     * MONTH   → ["2025年3月", "2026年2月", "2026年3月"]
     */
    private List<String> buildXAxisLabels(String type, int year, int quarter, int month) {
        List<String> labels = new ArrayList<>();
        switch (type == null ? "MONTH" : type) {
            case "YEAR":
                labels.add((year - 1) + "年");
                labels.add(year + "年");
                break;
            case "QUARTER": {
                labels.add((year - 1) + "年" + QUARTER_NAMES[quarter - 1] + "季度");
                int prevQ = quarter - 1, prevYear = year;
                if (prevQ < 1) { prevQ = 4; prevYear = year - 1; }
                labels.add(prevYear + "年" + QUARTER_NAMES[prevQ - 1] + "季度");
                labels.add(year + "年" + QUARTER_NAMES[quarter - 1] + "季度");
                break;
            }
            default: {
                labels.add((year - 1) + "年" + month + "月");
                int prevM = month - 1, prevYear = year;
                if (prevM < 1) { prevM = 12; prevYear = year - 1; }
                labels.add(prevYear + "年" + prevM + "月");
                labels.add(year + "年" + month + "月");
                break;
            }
        }
        return labels;
    }

    // -------------------------------------------------------------------------
    // 周期日期范围
    // -------------------------------------------------------------------------

    /**
     * 返回各周期日期范围（顺序与 xAxis 对应）
     * YEAR    → [去年全年, 今年全年]           (size=2)
     * QUARTER → [去年同季度, 上季度, 当季度]    (size=3)
     * MONTH   → [去年同月, 上月, 当月]          (size=3)
     */
    private List<LocalDate[]> buildPeriods(String type, int year, int quarter, int month) {
        List<LocalDate[]> periods = new ArrayList<>();
        switch (type == null ? "MONTH" : type) {
            case "YEAR":
                periods.add(yearRange(year - 1));
                periods.add(yearRange(year));
                break;
            case "QUARTER": {
                periods.add(quarterRange(year - 1, quarter));
                int prevQ = quarter - 1, prevYear = year;
                if (prevQ < 1) { prevQ = 4; prevYear = year - 1; }
                periods.add(quarterRange(prevYear, prevQ));
                periods.add(quarterRange(year, quarter));
                break;
            }
            default: {
                periods.add(monthRange(year - 1, month));
                int prevM = month - 1, prevYear = year;
                if (prevM < 1) { prevM = 12; prevYear = year - 1; }
                periods.add(monthRange(prevYear, prevM));
                periods.add(monthRange(year, month));
                break;
            }
        }
        return periods;
    }

    private LocalDate[] yearRange(int y) {
        return new LocalDate[]{LocalDate.of(y, 1, 1), LocalDate.of(y, 12, 31)};
    }

    private LocalDate[] quarterRange(int y, int q) {
        LocalDate start = LocalDate.of(y, (q - 1) * 3 + 1, 1);
        return new LocalDate[]{start, start.plusMonths(3).minusDays(1)};
    }

    private LocalDate[] monthRange(int y, int m) {
        LocalDate start = LocalDate.of(y, m, 1);
        return new LocalDate[]{start, start.withDayOfMonth(start.lengthOfMonth())};
    }

    // -------------------------------------------------------------------------
    // series 构建
    // -------------------------------------------------------------------------

    private List<Map<String, Object>> buildSeries(
            String scopeType, Long scopeId,
            List<String> xAxis, List<LocalDate[]> periods, boolean hasChain,
            boolean isStation, boolean isBrigade, boolean isManager,
            Long userDeptId, LoginUser loginUser) {

        int currentIdx = periods.size() - 1;

        if ("MANAGER".equals(scopeType) && scopeId != null) {
            List<Integer> counts = countByPeriods(periods, r -> countCompletedByDepartmentId(scopeId, r[0], r[1]));
            return Collections.singletonList(
                    buildSeriesItem(getDeptName(scopeId), scopeId, null, counts, currentIdx, hasChain));

        } else if ("USER".equals(scopeType) && scopeId != null) {
            List<Integer> counts = countByPeriods(periods, r -> countCompletedByUserId(scopeId, r[0], r[1]));
            return Collections.singletonList(
                    buildSeriesItem("用户" + scopeId, null, scopeId, counts, currentIdx, hasChain));

        } else if ("BRIGADE".equals(scopeType) && scopeId != null) {
            return buildBrigadeSeriesList(scopeId, periods, hasChain, currentIdx);

        } else if ("TEAM".equals(scopeType) && scopeId != null) {
            List<Integer> counts = countByPeriods(periods, r -> countCompletedByDepartmentId(scopeId, r[0], r[1]));
            return Collections.singletonList(
                    buildSeriesItem(getDeptName(scopeId), scopeId, null, counts, currentIdx, hasChain));

        } else {
            Long stationDeptId = ("STATION".equals(scopeType) && scopeId != null) ? scopeId : userDeptId;
            if (isStation || "STATION".equals(scopeType)) {
                return buildStationSeriesList(stationDeptId, periods, hasChain, currentIdx);
            } else if (isBrigade) {
                return buildBrigadeSeriesList(userDeptId, periods, hasChain, currentIdx);
            } else {
                // 主管：本主管室单条 series
                String deptName = loginUser.getUser().getDept() != null
                        ? loginUser.getUser().getDept().getDeptName() : "本主管";
                List<Integer> counts = countByPeriods(periods,
                        r -> countCompletedByDepartmentId(userDeptId, r[0], r[1]));
                return Collections.singletonList(
                        buildSeriesItem(deptName, userDeptId, null, counts, currentIdx, hasChain));
            }
        }
    }

    /**
     * 站长视角：各大队独立 series + 全站汇总
     */
    private List<Map<String, Object>> buildStationSeriesList(
            Long stationDeptId, List<LocalDate[]> periods, boolean hasChain, int currentIdx) {

        List<SysDept> subDepts = sysDeptMapper.selectChildrenDeptById(stationDeptId);
        if (subDepts == null) subDepts = Collections.emptyList();
        List<SysDept> brigades = subDepts.stream()
                .filter(d -> stationDeptId.equals(d.getParentId()) && "0".equals(d.getDelFlag()))
                .collect(Collectors.toList());

        List<Map<String, Object>> series = new ArrayList<>();
        int[] stationTotals = new int[periods.size()];

        for (SysDept brigade : brigades) {
            List<Integer> counts = countByPeriods(periods,
                    r -> countCompletedByBrigadeId(brigade.getDeptId(), r[0], r[1]));
            for (int i = 0; i < counts.size(); i++) stationTotals[i] += counts.get(i);
            series.add(buildSeriesItem(brigade.getDeptName(), brigade.getDeptId(), null, counts, currentIdx, hasChain));
        }

        List<Integer> totalCounts = new ArrayList<>();
        for (int c : stationTotals) totalCounts.add(c);
        series.add(buildSeriesItem("全站", null, null, totalCounts, currentIdx, hasChain));
        return series;
    }

    /**
     * 大队视角：各主管独立 series
     */
    private List<Map<String, Object>> buildBrigadeSeriesList(
            Long brigadeId, List<LocalDate[]> periods, boolean hasChain, int currentIdx) {

        List<SysDept> subDepts = sysDeptMapper.selectChildrenDeptById(brigadeId);
        if (subDepts == null) subDepts = Collections.emptyList();
        List<SysDept> managers = subDepts.stream()
                .filter(d -> brigadeId.equals(d.getParentId()) && "0".equals(d.getDelFlag()))
                .collect(Collectors.toList());

        List<Map<String, Object>> series = new ArrayList<>();
        for (SysDept manager : managers) {
            List<Integer> counts = countByPeriods(periods,
                    r -> countCompletedByDepartmentId(manager.getDeptId(), r[0], r[1]));
            series.add(buildSeriesItem(manager.getDeptName(), manager.getDeptId(), null, counts, currentIdx, hasChain));
        }
        return series;
    }

    // -------------------------------------------------------------------------
    // series item 构建
    // -------------------------------------------------------------------------

    /**
     * 构建单条 series
     *
     * @param counts     各周期完成数，顺序与 xAxis 对应
     * @param currentIdx 当期在 counts 中的下标（最后一个）
     * @param hasChain   是否计算环比
     */
    private Map<String, Object> buildSeriesItem(String name, Long deptId, Long userId,
                                                 List<Integer> counts, int currentIdx, boolean hasChain) {
        int currentVal = counts.get(currentIdx);
        int yoyVal = counts.get(0);
        Integer prevVal = hasChain ? counts.get(1) : null;

        Map<String, Object> s = new LinkedHashMap<>();
        s.put("name", name);
        if (deptId != null) s.put("deptId", deptId);
        if (userId != null) s.put("userId", userId);
        s.put("data", counts);
        s.put("yoyRate", calcRate(currentVal, yoyVal));
        s.put("chainRatio", prevVal != null ? calcRate(currentVal, prevVal) : null);
        return s;
    }

    // -------------------------------------------------------------------------
    // 统计辅助
    // -------------------------------------------------------------------------

    @FunctionalInterface
    interface PeriodCounter {
        int count(LocalDate[] range);
    }

    private List<Integer> countByPeriods(List<LocalDate[]> periods, PeriodCounter counter) {
        List<Integer> result = new ArrayList<>();
        for (LocalDate[] range : periods) {
            result.add(counter.count(range));
        }
        return result;
    }

    private int countCompletedByDepartmentId(Long deptId, LocalDate start, LocalDate end) {
        LambdaQueryWrapper<DailyTask> w = new LambdaQueryWrapper<>();
        w.eq(DailyTask::getDtDepartmentId, deptId);
        w.eq(DailyTask::getDtStatus, "COMPLETED");
        w.ge(DailyTask::getDtBusinessDate, Date.valueOf(start));
        w.le(DailyTask::getDtBusinessDate, Date.valueOf(end));
        w.eq(DailyTask::getDelStatus, 0);
        return Math.toIntExact(dailyTaskMapper.selectCount(w));
    }

    private int countCompletedByUserId(Long userId, LocalDate start, LocalDate end) {
        LambdaQueryWrapper<DailyTask> w = new LambdaQueryWrapper<>();
        w.eq(DailyTask::getDtUserId, userId);
        w.eq(DailyTask::getDtStatus, "COMPLETED");
        w.ge(DailyTask::getDtBusinessDate, Date.valueOf(start));
        w.le(DailyTask::getDtBusinessDate, Date.valueOf(end));
        w.eq(DailyTask::getDelStatus, 0);
        return Math.toIntExact(dailyTaskMapper.selectCount(w));
    }

    private int countCompletedByBrigadeId(Long brigadeId, LocalDate start, LocalDate end) {
        List<SysDept> subDepts = sysDeptMapper.selectChildrenDeptById(brigadeId);
        if (subDepts == null) subDepts = Collections.emptyList();
        Set<Long> managerIds = subDepts.stream()
                .filter(d -> brigadeId.equals(d.getParentId()) && "0".equals(d.getDelFlag()))
                .map(SysDept::getDeptId)
                .collect(Collectors.toSet());
        if (managerIds.isEmpty()) return 0;
        LambdaQueryWrapper<DailyTask> w = new LambdaQueryWrapper<>();
        w.in(DailyTask::getDtDepartmentId, managerIds);
        w.eq(DailyTask::getDtStatus, "COMPLETED");
        w.ge(DailyTask::getDtBusinessDate, Date.valueOf(start));
        w.le(DailyTask::getDtBusinessDate, Date.valueOf(end));
        w.eq(DailyTask::getDelStatus, 0);
        return Math.toIntExact(dailyTaskMapper.selectCount(w));
    }

    private String getDeptName(Long deptId) {
        SysDept dept = sysDeptMapper.selectDeptById(deptId);
        return dept != null ? dept.getDeptName() : "部门" + deptId;
    }

    private BigDecimal calcRate(int current, int base) {
        if (base == 0) return null;
        return BigDecimal.valueOf(current - base)
                .multiply(BigDecimal.valueOf(100))
                .divide(BigDecimal.valueOf(base), 2, RoundingMode.HALF_UP);
    }
}
