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

import cn.hutool.core.collection.CollectionUtil;
import com.sundot.airport.common.core.domain.AjaxResult;
import com.sundot.airport.common.core.domain.BaseLargeScreenQueryParamDto;
import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.domain.portrait.ApprovalDurationStats;
import com.sundot.airport.common.domain.portrait.IndicatorCalculateParams;
import com.sundot.airport.common.enums.DeptTypeEnum;
import com.sundot.airport.common.enums.RoleTypeEnum;
import com.sundot.airport.common.enums.portrait.UserType;
import com.sundot.airport.common.utils.DateUtils;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.item.domain.ItemLargeScreenCommonDto;
import com.sundot.airport.item.domain.ItemLargeScreenDailyTrendDto;
import com.sundot.airport.item.domain.ItemLargeScreenTimeSpanDto;
import com.sundot.airport.item.service.UserRankingService;
import com.sundot.airport.system.domain.approval.ApprovalInstance;
import com.sundot.airport.system.mapper.SysDeptMapper;
import com.sundot.airport.system.mapper.approval.ApprovalHistoryMapper;
import com.sundot.airport.system.mapper.approval.ApprovalInstanceMapper;
import com.sundot.airport.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/item/user-ranking")
public class ItemUserRankingController {

    @Autowired
    private UserRankingService userRankingService;

    @Autowired
    private ApprovalInstanceMapper approvalInstanceMapper;

    @Autowired
    private ApprovalHistoryMapper approvalHistoryMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    /**
     * 获取用户在指定层级的详细排名信息
     *
     * @param dto   查询参数
     * @param level 层级类型：station(全站), brigade(大队), department(科室), team(班组)
     * @return 用户在该层级的详细排名信息
     */
    @Cacheable(
            value = "item_ranking_detail",
            keyGenerator = "statisticsKeyGenerator",
            unless = "!T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isSuccess(#result) ||T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isEmptyData(#result)"
    )
    @PreAuthorize("@ss.hasPermi('item:record:list')")
    @GetMapping("/ranking-detail")
    public AjaxResult getUserRankingByLevel(BaseLargeScreenQueryParamDto dto,
                                            @RequestParam("level") String level) {
        ItemLargeScreenCommonDto ranking = userRankingService.getUserRankingByLevel(dto, level);
        return AjaxResult.success(ranking);
    }


    /**
     * 计算站级查获统计
     *
     * @param params 参数
     * @return 站级查获统计
     */
    @Cacheable(
            value = "item_station",
            keyGenerator = "statisticsKeyGenerator",
            unless = "!T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isSuccess(#result) ||T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isEmptyData(#result)"
    )
    @GetMapping("/station")
    public AjaxResult getStationItemSeizure(IndicatorCalculateParams params) {
        return AjaxResult.success(userRankingService.calculateStationItemSeizure(params));
    }

    /**
     * 查获审批时长统计
     *
     * @param params 查询参数
     * @return 平均审批时长 最长审批时长 最短审批时长
     */
    @Cacheable(
            value = "item_duration",
            keyGenerator = "statisticsKeyGenerator",
            unless = "!T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isSuccess(#result) ||T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isEmptyData(#result)"
    )
    @GetMapping("/seizure-approval/duration")
    public AjaxResult getSeizureApprovalDurationStats(IndicatorCalculateParams params) {
        // 设置默认时间范围
        java.util.Date endTime = Optional.ofNullable(params.getEndTime()).orElse(new java.util.Date());
        java.util.Date startTime = Optional.ofNullable(params.getStartTime())
                .orElse(java.util.Date.from(endTime.toInstant().minusSeconds(7862400L))); // 91天

        // 如果传了部门ID，则先查询该部门及其子部门下的所有用户ID
        List<Long> userIds = null;
        if (params.getDeptId() != null) {
            List<SysUser> sysUserList = sysUserMapper.selectUserListByRoleKeyAndDeptId(
                    Arrays.asList(RoleTypeEnum.banzuzhang.getCode(), RoleTypeEnum.SecurityCheck.getCode()),
                    params.getDeptId());
            userIds = sysUserList.stream().map(SysUser::getUserId).collect(Collectors.toList());
        }

        // 查询workflow_id为4或5的审批实例（查获审批流程）
        List<ApprovalInstance> instances = approvalInstanceMapper.selectApprovalInstancesByWorkflowIdsAndTimeRangeAndUsers(
                Arrays.asList(7L),
                startTime,
                endTime,
                userIds);

        if (instances.isEmpty()) {
            ApprovalDurationStats result = new ApprovalDurationStats();
            result.setAverageDuration(0L);
            result.setMaxDuration(0L);
            result.setMinDuration(0L);
            return AjaxResult.success(result);
        }

        // 计算每个实例的审批时长（毫秒）
        List<Long> durations = instances.stream()
                .map(instance -> {
                    Date submitTime = instance.getSubmitTime();
                    Date completionTime = instance.getCompletionTime();
                    if (submitTime != null && completionTime != null) {
                        return completionTime.getTime() - submitTime.getTime();
                    }
                    return 0L;
                })
                .filter(duration -> duration > 0)
                .collect(Collectors.toList());

        if (durations.isEmpty()) {
            ApprovalDurationStats result = new ApprovalDurationStats();
            result.setAverageDuration(0L);
            result.setMaxDuration(0L);
            result.setMinDuration(0L);
            return AjaxResult.success(result);
        }

        // 计算统计数据
        long totalDuration = durations.stream().mapToLong(Long::longValue).sum();
        long averageDuration = totalDuration / durations.size();
        long maxDuration = durations.stream().mapToLong(Long::longValue).max().orElse(0L);
        long minDuration = durations.stream().mapToLong(Long::longValue).min().orElse(0L);

        ApprovalDurationStats result = new ApprovalDurationStats();
        result.setAverageDuration(averageDuration);
        result.setMaxDuration(maxDuration);
        result.setMinDuration(minDuration);

        // 转换为小时和分钟显示
        result.setAverageDurationText(formatDuration(averageDuration));
        result.setMaxDurationText(formatDuration(maxDuration));
        result.setMinDurationText(formatDuration(minDuration));

        return AjaxResult.success(result);
    }

    /**
     * 格式化持续时间显示
     *
     * @param durationMillis 毫秒数
     * @return 格式化后的字符串，如"1天2小时30分钟45秒"
     */
    private String formatDuration(long durationMillis) {
        long seconds = durationMillis / 1000;
        long minutes = seconds / 60;
        long hours = minutes / 60;
        long days = hours / 24;

        seconds = seconds % 60;
        minutes = minutes % 60;
        hours = hours % 24;

        StringBuilder sb = new StringBuilder();
        if (days > 0) {
            sb.append(days).append("天");
        }
        if (hours > 0) {
            sb.append(hours).append("小时");
        }
        if (minutes > 0) {
            sb.append(minutes).append("分钟");
        }
        if (seconds > 0 || sb.length() == 0) {
            sb.append(seconds).append("秒");
        }
        return sb.toString();
    }

    /**
     * 查获趋势图，获取有效查获趋势数据（默认近90天）
     *
     * @param params 查询参数(科室就传部门id，站就可以不传参数)
     * @return 查获趋势数据
     */
    @Cacheable(
            value = "item_seizure_trend",
            keyGenerator = "statisticsKeyGenerator",
            unless = "!T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isSuccess(#result) ||T(com.sundot.airport.common.cache.StatisticsCacheConditionUtil).isEmptyData(#result)"
    )
    @GetMapping("/seizure-trend")
    public AjaxResult getSeizureTrendData(IndicatorCalculateParams params) {
        try {
            // 设置默认时间范围为近91天
            Date endTime = Optional.ofNullable(params.getEndTime()).orElse(new Date());
            Date startTime = Optional.ofNullable(params.getStartTime())
                    .orElse(Date.from(endTime.toInstant().minusSeconds(TimeUnit.DAYS.toSeconds(91))));

            // 参数校验
            if (startTime.after(endTime)) {
                return AjaxResult.error("开始时间不能晚于结束时间");
            }

            params.setStartTime(startTime);
            params.setEndTime(endTime);

            // 创建查询参数对象
            BaseLargeScreenQueryParamDto queryDto = new BaseLargeScreenQueryParamDto();
            queryDto.setStartDate(startTime);
            queryDto.setEndDate(endTime);

            // 如果传了部门ID，则设置到查询参数中
            if (params.getDeptId() != null) {
                SysDept sysDept = sysDeptMapper.selectDeptById(params.getDeptId());
                if (sysDept != null) {
                    if (DeptTypeEnum.BRIGADE.getCode().equals(sysDept.getDeptType())) {
                        queryDto.setInspectBrigadeId(params.getDeptId());
                    } else if (DeptTypeEnum.MANAGER.getCode().equals(sysDept.getDeptType())) {
                        queryDto.setInspectDepartmentId(params.getDeptId());
                    } else if (DeptTypeEnum.TEAMS.getCode().equals(sysDept.getDeptType())) {
                        queryDto.setInspectTeamId(params.getDeptId());
                    }
                }
            }

            // 调用service获取按天统计的查获趋势数据,没有的补0
            List<ItemLargeScreenDailyTrendDto> trendData = userRankingService.getDailyTrendData(queryDto);

            List<Date> dateRange = generateDateRange(startTime, endTime);
            // 创建一个Map来快速查找已有数据
            Map<Date, ItemLargeScreenDailyTrendDto> trendDataMap = trendData.stream()
                    .collect(Collectors.toMap(ItemLargeScreenDailyTrendDto::getDate, dto -> dto));

            // 构建完整的趋势数据列表，缺失日期补0
            List<ItemLargeScreenDailyTrendDto> completeTrendData = new ArrayList<>();
            for (Date date : dateRange) {
                if (trendDataMap.containsKey(date)) {
                    completeTrendData.add(trendDataMap.get(date));
                } else {
                    // 创建一个新的对象并设置日期和默认值
                    ItemLargeScreenDailyTrendDto emptyDto = new ItemLargeScreenDailyTrendDto();
                    emptyDto.setDate(date);
                    emptyDto.setTotal(BigDecimal.ZERO); // 假设没有查获记录时值为0
                    completeTrendData.add(emptyDto);
                }
            }

            return AjaxResult.success(completeTrendData);
        } catch (Exception e) {
            return AjaxResult.error("获取趋势数据失败：" + e.getMessage());
        }
    }

    /**
     * 生成日期范围列表
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return 日期范围列表
     */
    private List<Date> generateDateRange(Date startDate, Date endDate) throws ParseException {
        List<Date> dateRange = new ArrayList<>();

        // 使用UTC时区确保一致性
        ZoneId zoneId = ZoneId.of("UTC");
        LocalDate start = startDate.toInstant().atZone(zoneId).toLocalDate();
        LocalDate end = endDate.toInstant().atZone(zoneId).toLocalDate();

        // 计算天数差
        long daysBetween = ChronoUnit.DAYS.between(start, end);

        // 生成日期范围（包括起始和结束日期）
        for (int i = 0; i <= daysBetween; i++) {
            LocalDate currentDate = start.plusDays(i);
            dateRange.add(DateUtils.parseDate(currentDate.toString(), "yyyy-MM-dd"));
        }

        return dateRange;
    }
}