package com.ygtx.gxt.service.impl;

import com.ygtx.common.constant.Constants;
import com.ygtx.common.core.domain.entity.SysRole;
import com.ygtx.common.core.domain.entity.SysUser;
import com.ygtx.common.core.domain.model.LoginUser;
import com.ygtx.common.utils.SecurityUtils;
import com.ygtx.common.utils.StringUtils;
import com.ygtx.framework.aspectj.DataScopeAspect;
import com.ygtx.gxt.domain.*;
import com.ygtx.gxt.mapper.*;
import com.ygtx.gxt.service.IGxtOrderHourService;
import com.ygtx.gxt.service.IGxtRepairOrderService;
import com.ygtx.gxt.service.IGxtWorkOrderService;
import com.ygtx.system.mapper.SysUserMapper;
import com.ygtx.system.service.ISysConfigService;
import com.ygtx.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 工单工时Service业务层处理
 *
 * @author ouyj
 * @date 2025-11-12
 */
@Service
public class GxtOrderHourServiceImpl implements IGxtOrderHourService {

    @Autowired
    private GxtOrderHourMapper gxtOrderHourMapper;
    
    @Autowired
    private IGxtRepairOrderService gxtRepairOrderService;
    
    @Autowired
    private IGxtWorkOrderService gxtWorkOrderService;
    
    @Autowired
    private GxtRepairOrderFlowMapper gxtRepairOrderFlowMapper;
    
    @Autowired
    private GxtWorkOrderFlowMapper gxtWorkOrderFlowMapper;
    
    @Autowired
    private GxtRepairOrderPersonMapper gxtRepairOrderPersonMapper;
    
    @Autowired
    private GxtWorkOrderPersonMapper gxtWorkOrderPersonMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ISysConfigService configService;

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

    /**
     * 查询合并的工单列表（维修工单和维保工单）
     *
     * @param repairOrder 维修工单查询条件
     * @param workOrder 维保工单查询条件
     * @param orderType 工单类型筛选条件
     * @param timeRange 时间范围参数 (week:本周, month:本月, custom:自定义)
     * @param beginDate 自定义开始时间
     * @param endDate 自定义结束时间
     * @param keyword 搜索关键字
     * @return 合并的工单列表
     */
    @Override
    public List<OrderScoreInfo> selectUnionOrderList(GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String orderType, String timeRange, String beginDate, String endDate, String keyword) {
        // 处理时间范围参数
        processTimeRange(repairOrder, workOrder, timeRange, beginDate, endDate);

        // 添加业务特定的数据权限过滤
        addBusinessDataScopeFilter(repairOrder, workOrder);

        // 设置创建人，用于数据权限过滤
        if(!Constants.SUPER_ADMIN.equals(SecurityUtils.getUsername())){
            if (repairOrder.getCreateBy() == null || repairOrder.getCreateBy().isEmpty()) {
                repairOrder.setCreateBy(SecurityUtils.getUsername());
            }

            if (workOrder.getCreateBy() == null || workOrder.getCreateBy().isEmpty()) {
                workOrder.setCreateBy(SecurityUtils.getUsername());
            }
        }
        // 查询工单列表
        List<OrderScoreInfo> orderList = gxtOrderHourMapper.selectUnionOrderList(repairOrder, workOrder, orderType, keyword);
        
        // 计算每个工单的作业时长
        for (OrderScoreInfo order : orderList) {
            /*double processingHours = calculateOrderProcessingHours(order);
            order.setHandleHour(processingHours);*/
            long[] suspensionTimes = new long[3]; // 总挂起时长, 开工前挂起时长, 开工挂起后时长
            if (order.getOrderType() == 1) { // 维修工单
                suspensionTimes = calculateRepairOrderSuspensionTime(order.getId());
            } else if (order.getOrderType() == 2) { // 维保工单
                suspensionTimes = calculateWorkOrderSuspensionTime(order.getId());
            }
            if (order.getRealEndTime() != null && order.getRealStartTime() != null) {
                long diffMillis = order.getRealEndTime().getTime() - order.getRealStartTime().getTime() - suspensionTimes[2] ;
                order.setWorkHour(diffMillis / (1000.0 * 60 * 60));
            }
            if (order.getOrderType() == 1) {
                // 维修工单
                List<GxtRepairOrderPerson> repairPersons = gxtRepairOrderService.selectRepairOrderPersonListByOrderId(order.getId());
                // 检查当前用户是否在维修工单人员列表中
                boolean isCurrentUserInOrder = false;
                for (GxtRepairOrderPerson person : repairPersons) {
                    if (Objects.equals(person.getUserId(), SecurityUtils.getUserId())) {
                        isCurrentUserInOrder = true;
                        break;
                    }
                }
                order.setIsCurrentUserInOrder(isCurrentUserInOrder);
            } else if (order.getOrderType() == 2) {
                // 维保工单
                List<GxtWorkOrderPerson> workPersons = gxtWorkOrderService.selectWorkOrderPersonListByOrderId(order.getId());
                // 检查当前用户是否在维保工单人员列表中
                boolean isCurrentUserInOrder = false;
                for (GxtWorkOrderPerson person : workPersons) {
                    if (Objects.equals(person.getUserId(), SecurityUtils.getUserId())) {
                        isCurrentUserInOrder = true;
                        break;
                    }
                }
                order.setIsCurrentUserInOrder(isCurrentUserInOrder);
            }
        }
        return orderList;
    }

    /**
     * 获取工单工时统计信息
     *
     * @param repairOrder 维修工单查询条件
     * @param workOrder 维保工单查询条件
     * @param orderType 工单类型筛选条件
     * @param timeRange 时间范围参数 (week:本周, month:本月, custom:自定义)
     * @param beginDate 自定义开始时间
     * @param endDate 自定义结束时间
     * @param keyword 搜索关键字
     * @return 统计信息
     */
    @Override
    public Map<String, Object> getOrderHourStatistics(GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String orderType, String timeRange, String beginDate, String endDate, String keyword) {
        // 处理时间范围参数
        processTimeRange(repairOrder, workOrder, timeRange, beginDate, endDate);

        /*// 添加业务特定的数据权限过滤
        addBusinessDataScopeFilter(repairOrder, workOrder);

        // 设置创建人，用于数据权限过滤
        if(!Constants.SUPER_ADMIN.equals(SecurityUtils.getUsername())){
            if (repairOrder.getCreateBy() == null || repairOrder.getCreateBy().isEmpty()) {
                repairOrder.setCreateBy(SecurityUtils.getUsername());
            }

            if (workOrder.getCreateBy() == null || workOrder.getCreateBy().isEmpty()) {
                workOrder.setCreateBy(SecurityUtils.getUsername());
            }
        }*/
        
        // 对所有人，只统计个人参与的工单工时
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser != null && loginUser.getUser() != null) {
            Long userId = loginUser.getUser().getUserId();
            
            // 为维修工单添加用户筛选条件
            if (repairOrder != null) {
                StringBuilder repairUserFilter = new StringBuilder();
                repairUserFilter.append("( t.id IN (SELECT order_id FROM gxt_repair_order_person WHERE user_id = ").append(userId).append("))");
                
                // 如果已有businessDataScope条件，追加到现有条件中
                if (repairOrder.getParams().containsKey("businessDataScope")) {
                    String existingCondition = (String) repairOrder.getParams().get("businessDataScope");
                    repairOrder.getParams().put("businessDataScope", existingCondition + " AND (" + repairUserFilter.toString() + ")");
                } else {
                    repairOrder.getParams().put("businessDataScope", " AND (" + repairUserFilter.toString() + ")");
                }
            }
            
            // 为维保工单添加用户筛选条件
            if (workOrder != null) {
                StringBuilder workUserFilter = new StringBuilder();
                workUserFilter.append("( t.id IN (SELECT order_id FROM gxt_work_order_person WHERE user_id = ").append(userId).append("))");
                
                // 如果已有businessDataScope条件，追加到现有条件中
                if (workOrder.getParams().containsKey("businessDataScope")) {
                    String existingCondition = (String) workOrder.getParams().get("businessDataScope");
                    workOrder.getParams().put("businessDataScope", existingCondition + " AND (" + workUserFilter.toString() + ")");
                } else {
                    workOrder.getParams().put("businessDataScope", " AND (" + workUserFilter.toString() + ")");
                }
            }
        }

        // 获取统计数据
        List<OrderScoreInfo> orderList = gxtOrderHourMapper.selectUnionOrderList(repairOrder, workOrder, orderType, keyword);
        
        // 计算统计信息
        Map<String, Object> statistics = new HashMap<>();
        
        double totalHours = 0;
        double maintenanceHours = 0;
        double repairHours = 0;
        int maintenanceCount = 0;
        int repairCount = 0;
        
        for (OrderScoreInfo order : orderList) {
            // 使用专门计算作业时长的方法
            double hours = calculateWorkHours(order);

            
            if (order.getOrderType() == 2) { // 维保工单
                maintenanceHours += hours;
                maintenanceCount++;
            } else if (order.getOrderType() == 1) { // 维修工单
                repairHours += hours;
                repairCount++;
            }
        }
        totalHours = BigDecimal.valueOf(maintenanceHours).setScale(2, RoundingMode.HALF_UP)
                .add(BigDecimal.valueOf(repairHours).setScale(2, RoundingMode.HALF_UP))
                .doubleValue();
        statistics.put("totalHours", totalHours);
        statistics.put("maintenanceHours", maintenanceHours);
        statistics.put("repairHours", repairHours);
        statistics.put("maintenanceCount", maintenanceCount);
        statistics.put("repairCount", repairCount);
        statistics.put("orderCount", orderList.size());
        
        /*// 如果用户的数据权限是"仅本人数据"，则计算排名
        if (isCurrentUserDataScopeSelf()) {
            int rank = calculateUserRankInStation(repairOrder, workOrder, orderType, timeRange, beginDate, endDate, keyword);
            statistics.put("rank", rank);
            
            // 计算场站总人数
            //LoginUser loginUser = SecurityUtils.getLoginUser();
            if (loginUser != null && loginUser.getUser() != null) {
                Long deptId = loginUser.getUser().getDeptId();
                if (deptId != null) {
                    int totalUsersInStation = getStationUserIds(deptId).size();
                    statistics.put("totalRankingUsers", totalUsersInStation);
                }
            }
        }*/
        
        return statistics;
    }

    /**
     * 判断当前用户的数据权限是否为"仅本人数据"
     * 
     * @return true表示数据权限为"仅本人数据"，false表示其他权限
     */
    private boolean isCurrentUserDataScopeSelf() {
        // 获取当前登录用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return false;
        }

        SysUser currentUser = loginUser.getUser();
        if (currentUser == null) {
            return false;
        }

        // 如果是超级管理员，不过滤数据
        if (currentUser.isAdmin()) {
            return false;
        }

        // 获取用户角色
        List<SysRole> roles = currentUser.getRoles();
        if (roles == null || roles.isEmpty()) {
            return false;
        }

        // 检查所有角色的数据权限是否都是"仅本人数据"
        for (SysRole role : roles) {
            String dataScope = role.getDataScope();
            // 如果有任何一个角色不是"仅本人数据"权限，则不显示排名
            if (!DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
                return false;
            }
        }
        
        // 所有角色都是"仅本人数据"权限
        return true;
    }
    
    /**
     * 计算用户在所在场站的排名
     * 
     * @return 用户在所在场站的排名
     */
    private int calculateUserRankInStation(GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String orderType, String timeRange, String beginDate, String endDate, String keyword) {
        // 获取当前登录用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return -1;
        }

        SysUser currentUser = loginUser.getUser();
        if (currentUser == null || currentUser.getUserId() == null) {
            return -1;
        }
        
        Long userId = currentUser.getUserId();
        Long deptId = currentUser.getDeptId();
        
        // 检查是否有部门ID
        if (deptId == null) {
            return -1; // 没有部门信息，无法计算排名
        }
        
        // 获取当前用户处理的工单工时
        double currentUserWorkHours = getUserWorkHours(userId, repairOrder, workOrder, orderType, timeRange, beginDate, endDate, keyword);
        
        // 获取同一场站其他用户的工单工时
        List<Map<String, Object>> stationUserWorkHours = getStationUserWorkHours(deptId, repairOrder, workOrder, orderType, timeRange, beginDate, endDate, keyword);
        
        // 检查是否获取到用户数据
        if (stationUserWorkHours == null || stationUserWorkHours.isEmpty()) {
            return -1;
        }
        
        // 计算排名
        int rank = 1;
        for (Map<String, Object> userWorkHour : stationUserWorkHours) {
            if (userWorkHour == null || userWorkHour.get("userId") == null || userWorkHour.get("workHours") == null) {
                continue;
            }
            
            Long userIdInStation = (Long) userWorkHour.get("userId");
            double workHours = (Double) userWorkHour.get("workHours");
            
            // 跳过当前用户自己
            if (userIdInStation.equals(userId)) {
                continue;
            }
            
            // 如果其他用户的工时大于当前用户，则排名下降
            if (workHours > currentUserWorkHours) {
                rank++;
            }
        }
        
        return rank;
    }
    
    /**
     * 获取用户处理的工单工时
     * 
     * @param userId 用户ID
     * @return 用户处理的工单工时
     */
    private double getUserWorkHours(Long userId, GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String orderType, String timeRange, String beginDate, String endDate, String keyword) {
        // 复制查询条件
        GxtRepairOrder userRepairOrder = new GxtRepairOrder();
        if (repairOrder != null) {
            try {
                org.springframework.beans.BeanUtils.copyProperties(repairOrder, userRepairOrder);
                // 复制参数
                Map<String, Object> params = new HashMap<>();
                params.putAll(repairOrder.getParams());
                userRepairOrder.setParams(params);
            } catch (Exception e) {
                // 忽略拷贝异常
            }
        }
        
        GxtWorkOrder userWorkOrder = new GxtWorkOrder();
        if (workOrder != null) {
            try {
                org.springframework.beans.BeanUtils.copyProperties(workOrder, userWorkOrder);
                // 复制参数
                Map<String, Object> params = new HashMap<>();
                params.putAll(workOrder.getParams());
                userWorkOrder.setParams(params);
            } catch (Exception e) {
                // 忽略拷贝异常
            }
        }
        
        // 为维修工单添加用户筛选条件
        if (userRepairOrder != null) {
            StringBuilder repairUserFilter = new StringBuilder();
            repairUserFilter.append("( t.id IN (SELECT order_id FROM gxt_repair_order_person WHERE user_id = ").append(userId).append("))");

            userRepairOrder.getParams().put("businessDataScope", " AND (" + repairUserFilter.toString() + ")");
        }
        
        // 为维保工单添加用户筛选条件
        if (userWorkOrder != null) {
            StringBuilder workUserFilter = new StringBuilder();
            workUserFilter.append("( t.id IN (SELECT order_id FROM gxt_work_order_person WHERE user_id = ").append(userId).append("))");

            userWorkOrder.getParams().put("businessDataScope", " AND (" + workUserFilter.toString() + ")");
        }
        
        // 处理时间范围参数
        processTimeRange(userRepairOrder, userWorkOrder, timeRange, beginDate, endDate);
        
        // 查询用户处理的工单
        List<OrderScoreInfo> userOrders = gxtOrderHourMapper.selectUnionOrderList(userRepairOrder, userWorkOrder, orderType, keyword);
        
        // 计算总工时
        double totalHours = 0;
        for (OrderScoreInfo order : userOrders) {
            double hours = calculateWorkHours(order);
            totalHours += hours;
        }
        
        return totalHours;
    }
    
    /**
     * 获取场站内所有用户的工单工时
     * 
     * @param deptId 场站ID
     * @return 场站内所有用户的工单工时列表
     */
    private List<Map<String, Object>> getStationUserWorkHours(Long deptId, GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String orderType, String timeRange, String beginDate, String endDate, String keyword) {
        List<Map<String, Object>> result = new ArrayList<>();
        List<Long> stationUserIds = getStationUserIds(deptId);

        // 逐个计算场站内每个用户的工时
        for (Long userId : stationUserIds) {
            double userWorkHours = getUserWorkHours(userId, repairOrder, workOrder, orderType, timeRange, beginDate, endDate, keyword);
            Map<String, Object> userWorkHour = new HashMap<>();
            userWorkHour.put("userId", userId);
            userWorkHour.put("workHours", userWorkHours);
            result.add(userWorkHour);
        }
        return result;
    }
    
    /**
     * 获取场站内所有用户ID
     * 
     * @param deptId 场站ID
     * @return 场站内所有用户ID列表
     */
    private List<Long> getStationUserIds(Long deptId) {
        if (deptId == null) {
            return new ArrayList<>(); // 返回空列表而不是null
        }
        
        SysUser user = new SysUser();
        user.setDeptId(deptId);
        List<SysUser> sysUsers = userMapper.selectUserListByDeptId(user);
        List<Long> userIds = new ArrayList<>();
        if (sysUsers != null) {
            sysUsers.forEach(sysUser -> {
                if (sysUser != null && sysUser.getUserId() != null) {
                    userIds.add(sysUser.getUserId());
                }
            });
        }
        return userIds;
    }
    
    /**
     * 处理时间范围参数
     * @param repairOrder 维修工单查询条件
     * @param workOrder 维保工单查询条件
     * @param timeRange 时间范围参数 (week:本周, month:本月, custom:自定义)
     * @param beginDate 自定义开始时间
     * @param endDate 自定义结束时间
     */
    private void processTimeRange(GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String timeRange, String beginDate, String endDate) {
        if (timeRange == null || timeRange.isEmpty()) {
            return;
        }
        
        Date startTime = null;
        Date endTime = null;
        
        switch (timeRange) {
            case "week":
                // 本周开始时间(周一)
                startTime = getWeekStart();
                // 本周结束时间(周日)
                endTime = getWeekEnd();
                break;
            case "month":
                // 本月开始时间
                startTime = getMonthStart();
                // 本月结束时间
                endTime = getMonthEnd();
                break;
            case "custom":
                // 自定义时间范围
                if (beginDate != null && !beginDate.isEmpty() && endDate != null && !endDate.isEmpty()) {
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        // 开始时间设置为当天的00:00:00
                        startTime = sdf.parse(beginDate);
                        // 结束时间设置为当天的23:59:59
                        endTime = sdf.parse(endDate);
                        
                        // 调整结束时间为当天的最后一毫秒
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(endTime);
                        cal.set(Calendar.HOUR_OF_DAY, 23);
                        cal.set(Calendar.MINUTE, 59);
                        cal.set(Calendar.SECOND, 59);
                        cal.set(Calendar.MILLISECOND, 999);
                        endTime = cal.getTime();
                    } catch (ParseException e) {
                        // 解析失败则不设置时间范围
                        return;
                    }
                }
                break;
            default:
                // 对于其他情况，不设置时间限制
                return;
        }
        
        // 为维修工单设置时间范围（使用occurTime）
        //待修改，改为维修工单设置时间范围，改成结单时间，即gxt_repair_order_flow里面action_type值为complete的action_time的值
        if (repairOrder != null) {
            //repairOrder.getParams().put("beginOccurTime", startTime);
            //repairOrder.getParams().put("endOccurTime", endTime);
            //repairOrder.getParams().put("beginCompleteTime", startTime);
            //repairOrder.getParams().put("endCompleteTime", endTime);
            repairOrder.getParams().put("beginRealEndTime", startTime);
            repairOrder.getParams().put("endRealEndTime", endTime);
        }
        
        // 为维保工单设置时间范围（使用createTime）
        //待修改，改为维保工单设置时间范围，改成结单时间，即gxt_work_order_flow里面action_type为action_type值为complete的action_time的值
        if (workOrder != null) {
            //workOrder.getParams().put("beginCreateTime", startTime);
            //workOrder.getParams().put("endCreateTime", endTime);
            //workOrder.getParams().put("beginCompleteTime", startTime);
            //workOrder.getParams().put("endCompleteTime", endTime);
            workOrder.getParams().put("beginRealEndTime", startTime);
            workOrder.getParams().put("endRealEndTime", endTime);
        }
    }
    
    /**
     * 获取本周开始时间（周一）
     */
    private Date getWeekStart() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }
    
    /**
     * 获取本周结束时间（周日）
     */
    private Date getWeekEnd() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek() + 6);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }
    
    /**
     * 获取本月开始时间
     */
    private Date getMonthStart() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }
    
    /**
     * 获取本月结束时间
     */
    private Date getMonthEnd() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }
    
    /**
     * 添加业务特定的数据权限过滤条件
     * 基于角色的数据范围进行自定义权限控制
     *
     * @param repairOrder 维修工单查询条件
     * @param workOrder 维保工单查询条件
     */
    private void addBusinessDataScopeFilter(GxtRepairOrder repairOrder, GxtWorkOrder workOrder) {
        // 获取当前登录用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return;
        }

        SysUser currentUser = loginUser.getUser();
        if (currentUser == null) {
            return;
        }

        // 如果是超级管理员，不过滤数据
        if (currentUser.isAdmin()) {
            return;
        }

        // 获取用户角色
        List<SysRole> roles = currentUser.getRoles();
        if (roles == null || roles.isEmpty()) {
            // 如果用户没有任何角色，则不返回任何数据
            String noDataCondition = " AND 1=0";
            workOrder.getParams().put("businessDataScope", noDataCondition);
            repairOrder.getParams().put("businessDataScope", noDataCondition);
            return;
        }

        // 检查是否有"全部数据"权限的角色
        boolean hasAllDataPermission = roles.stream()
                .anyMatch(role -> DataScopeAspect.DATA_SCOPE_ALL.equals(role.getDataScope()));

        // 如果有任何一个角色有全部数据权限，则不过滤数据范围
        if (!hasAllDataPermission) {
            // 构建业务特定的数据权限SQL
            StringBuilder orderBusinessSql = new StringBuilder();
            StringBuilder repairBusinessSql = new StringBuilder();

            // 遍历用户角色，根据角色的数据范围添加业务特定的权限控制
            for (SysRole role : roles) {
                String dataScope = role.getDataScope();

                // 自定义数据权限 - 根据角色的数据范围值来控制查询条件
                if (DataScopeAspect.DATA_SCOPE_CUSTOM.equals(dataScope)) {
                    // 获取具有自定义数据权限的角色ID列表
                    List<String> customRoleIds = new ArrayList<>();
                    for (SysRole r : roles) {
                        if (DataScopeAspect.DATA_SCOPE_CUSTOM.equals(r.getDataScope())) {
                            customRoleIds.add(String.valueOf(r.getRoleId()));
                        }
                    }

                    // 构建自定义数据权限查询条件
                    if (orderBusinessSql.length() > 0) {
                        orderBusinessSql.append(" OR ");
                    }
                    // 构建自定义数据权限查询条件
                    if (repairBusinessSql.length() > 0) {
                        repairBusinessSql.append(" OR ");
                    }

                    if (customRoleIds.size() > 1) {
                        // 多个自定义数据权限角色使用IN查询
                        orderBusinessSql.append("(t.pcs_station_pid IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN (")
                                .append(String.join(",", customRoleIds))
                                .append("))")
                                .append(" OR t.pcs_station_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN (")
                                .append(String.join(",", customRoleIds))
                                .append("))")
                                .append(" OR t.gxt_center_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN (")
                                .append(String.join(",", customRoleIds))
                                .append(")))");
                        repairBusinessSql.append("(t.pcs_station_pid IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN (")
                                .append(String.join(",", customRoleIds))
                                .append("))")
                                .append(" OR t.pcs_station_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN (")
                                .append(String.join(",", customRoleIds))
                                .append("))")
                                .append(" OR t.gxt_center_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN (")
                                .append(String.join(",", customRoleIds))
                                .append(")))");
                    } else {
                        // 单个自定义数据权限角色查询
                        orderBusinessSql.append("(t.pcs_station_pid IN (SELECT dept_id FROM sys_role_dept WHERE role_id = ")
                                .append(role.getRoleId())
                                .append(")")
                                .append(" OR t.pcs_station_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id = ")
                                .append(role.getRoleId())
                                .append(")")
                                .append(" OR t.gxt_center_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id = ")
                                .append(role.getRoleId())
                                .append("))");
                        repairBusinessSql.append("(t.pcs_station_pid IN (SELECT dept_id FROM sys_role_dept WHERE role_id = ")
                                .append(role.getRoleId())
                                .append(")")
                                .append(" OR t.pcs_station_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id = ")
                                .append(role.getRoleId())
                                .append(")")
                                .append(" OR t.gxt_center_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id = ")
                                .append(role.getRoleId())
                                .append("))");
                    }
                    continue;
                }

                // 部门数据权限 - 适用于部门负责人角色
                if (DataScopeAspect.DATA_SCOPE_DEPT.equals(dataScope)) {
                    if (orderBusinessSql.length() > 0) {
                        orderBusinessSql.append(" OR ");
                    }
                    if (repairBusinessSql.length() > 0) {
                        repairBusinessSql.append(" OR ");
                    }
                    orderBusinessSql.append("(t.pcs_station_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR t.pcs_station_pid = ")
                            .append(currentUser.getDeptId())
                            .append(" OR t.gxt_center_id = ")
                            .append(currentUser.getDeptId())
                            .append(")");
                    repairBusinessSql.append("(t.pcs_station_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR t.pcs_station_pid = ")
                            .append(currentUser.getDeptId())
                            .append(" OR t.gxt_center_id = ")
                            .append(currentUser.getDeptId())
                            .append(")");
                    continue;
                }

                // 部门及以下数据权限
                if (DataScopeAspect.DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
                    if (orderBusinessSql.length() > 0) {
                        orderBusinessSql.append(" OR ");
                    }
                    if (repairBusinessSql.length() > 0) {
                        repairBusinessSql.append(" OR ");
                    }
                    orderBusinessSql.append("(t.pcs_station_id IN ")
                            .append("(SELECT dept_id FROM sys_dept WHERE dept_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR FIND_IN_SET(")
                            .append(currentUser.getDeptId())
                            .append(", ancestors))")
                            .append(" OR t.pcs_station_pid IN ")
                            .append("(SELECT dept_id FROM sys_dept WHERE dept_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR FIND_IN_SET(")
                            .append(currentUser.getDeptId())
                            .append(", ancestors))")
                            .append(" OR t.gxt_center_id IN ")
                            .append("(SELECT dept_id FROM sys_dept WHERE dept_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR FIND_IN_SET(")
                            .append(currentUser.getDeptId())
                            .append(", ancestors)))");
                    repairBusinessSql.append("(t.pcs_station_id IN ")
                            .append("(SELECT dept_id FROM sys_dept WHERE dept_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR FIND_IN_SET(")
                            .append(currentUser.getDeptId())
                            .append(", ancestors))")
                            .append(" OR t.pcs_station_pid IN ")
                            .append("(SELECT dept_id FROM sys_dept WHERE dept_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR FIND_IN_SET(")
                            .append(currentUser.getDeptId())
                            .append(", ancestors))")
                            .append(" OR t.gxt_center_id IN ")
                            .append("(SELECT dept_id FROM sys_dept WHERE dept_id = ")
                            .append(currentUser.getDeptId())
                            .append(" OR FIND_IN_SET(")
                            .append(currentUser.getDeptId())
                            .append(", ancestors)))");
                    continue;
                }

                // 仅本人数据权限 - 适用于主检修员角色
                if (DataScopeAspect.DATA_SCOPE_SELF.equals(dataScope)) {
                    if (orderBusinessSql.length() > 0) {
                        orderBusinessSql.append(" OR ");
                    }
                    if (repairBusinessSql.length() > 0) {
                        repairBusinessSql.append(" OR ");
                    }
                    orderBusinessSql.append("(t.team_leader_id = ")
                            .append(currentUser.getUserId())
                            .append(" OR t.assign_user_id = ")
                            .append(currentUser.getUserId())
                            .append(" OR t.accept_user_id = ")
                            .append(currentUser.getUserId())
                            .append(" OR t.id IN (SELECT order_id FROM gxt_work_order_person WHERE user_id = ")
                            .append(currentUser.getUserId())
                            .append(") ")
                            .append(" OR t.create_by = '")
                            .append(currentUser.getUserName())
                            .append("')");
                    repairBusinessSql.append("(t.team_leader_id = ")
                            .append(currentUser.getUserId())
                            .append(" OR t.assign_user_id = ")
                            .append(currentUser.getUserId())
                            .append(" OR t.accept_user_id = ")
                            .append(currentUser.getUserId())
                            .append(" OR t.id IN (SELECT order_id FROM gxt_repair_order_person WHERE user_id = ")
                            .append(currentUser.getUserId())
                            .append(") ")
                            .append(" OR t.create_by = '")
                            .append(currentUser.getUserName())
                            .append("')");
                    continue;
                }
            }
            String selfData = configService.selectConfigByKey("gxt.oder.selfData");
            if (StringUtils.isNotEmpty(selfData) && "1".equals(selfData)) {
                if (orderBusinessSql.length() > 0) {
                    orderBusinessSql.append(" OR ");
                }
                if (repairBusinessSql.length() > 0) {
                    repairBusinessSql.append(" OR ");
                }
                orderBusinessSql.append("(t.team_leader_id = ")
                        .append(currentUser.getUserId())
                        .append(" OR t.assign_user_id = ")
                        .append(currentUser.getUserId())
                        .append(" OR t.accept_user_id = ")
                        .append(currentUser.getUserId())
                        .append(" OR t.id IN (SELECT order_id FROM gxt_work_order_person WHERE user_id = ")
                        .append(currentUser.getUserId())
                        .append(") ")
                        .append(" OR t.create_by = '")
                        .append(currentUser.getUserName())
                        .append("')");
                repairBusinessSql.append("(t.team_leader_id = ")
                        .append(currentUser.getUserId())
                        .append(" OR t.assign_user_id = ")
                        .append(currentUser.getUserId())
                        .append(" OR t.accept_user_id = ")
                        .append(currentUser.getUserId())
                        .append(" OR t.id IN (SELECT order_id FROM gxt_repair_order_person WHERE user_id = ")
                        .append(currentUser.getUserId())
                        .append(") ")
                        .append(" OR t.create_by = '")
                        .append(currentUser.getUserName())
                        .append("')");
            }
            // 如果构建了业务特定的过滤条件，则添加到查询参数中
            if (orderBusinessSql.length() > 0) {
                String businessDataScopeSql = " AND (" + orderBusinessSql.toString() + ")";
                workOrder.getParams().put("businessDataScope", businessDataScopeSql);
            }
            if (repairBusinessSql.length() > 0) {
                String businessDataScopeSql = " AND (" + repairBusinessSql.toString() + ")";
                repairOrder.getParams().put("businessDataScope", businessDataScopeSql);
            }
        }
        
        // 对于已作废(work_order_status = 'invalid')的工单，只有admin用户才能查看
        if (!SecurityUtils.isAdmin(currentUser.getUserId())) {
            String invalidFilterSql = " AND (t.work_order_status != 'invalid')";
            if (workOrder.getParams().get("businessDataScope") != null) {
                String existingSql = workOrder.getParams().get("businessDataScope").toString();
                workOrder.getParams().put("businessDataScope", existingSql + invalidFilterSql);
            } else {
                workOrder.getParams().put("businessDataScope", invalidFilterSql);
            }
            if (repairOrder.getParams().get("businessDataScope") != null) {
                String existingSql = repairOrder.getParams().get("businessDataScope").toString();
                repairOrder.getParams().put("businessDataScope", existingSql + invalidFilterSql);
            } else {
                repairOrder.getParams().put("businessDataScope", invalidFilterSql);
            }
        }
    }
    
    /**
     * 计算单个工单的处理时长（小时）
     * 处理时长 = 复运时间restartTime – 故障发生时间（维修工单用occurTime，维保工单用createTime） – 挂起时长
     * 挂起时长 = 恢复时间 - 挂起时间
     * 
     * @param order 工单信息
     * @return 处理时长（小时）
     */
    private double calculateOrderProcessingHours(OrderScoreInfo order) {
        // 只有存在复运时间的工单才进行统计计算
        if (order.getRestartTime() == null) {
            return 0;
        }
        
        Date startTime = null;
        if (order.getOrderType() == 1) { // 维修工单
            startTime = order.getOccurTime();
        } else if (order.getOrderType() == 2) { // 维保工单
            startTime = order.getCreateTime();
        }
        
        if (startTime == null) {
            return 0;
        }
        
        // 计算总挂起时长（毫秒）
        long suspensionDuration = 0;
        if (order.getOrderType() == 1) { // 维修工单
            long[] suspensionTimes = calculateRepairOrderSuspensionTime(order.getId());
            suspensionDuration = suspensionTimes[0];
        } else if (order.getOrderType() == 2) { // 维保工单
            long[] suspensionTimes = calculateWorkOrderSuspensionTime(order.getId());
            suspensionDuration = suspensionTimes[0];
        }
        
        // 计算处理时长 = (复运时间 - 开始时间 - 挂起时长) / 小时
        long totalDuration = order.getRestartTime().getTime() - startTime.getTime();
        long processingDuration = totalDuration - suspensionDuration;
        
        // 转换为小时
        return processingDuration / (1000.0 * 60 * 60);
    }

    /**
     * 计算维修工单的挂起时长，分为开工前和开工后两部分
     * 维修工单挂起对应的actionType是approved，恢复对应的是resume
     * 自动挂起对应的actionType是auto_suspend，恢复对应的是auto_resume
     *
     * @param orderId 工单ID
     * @return 包含总挂起时长、开工前挂起时长、开工后挂起时长的数组，索引0为总时长，索引1为开工前时长，索引2为开工后时长（毫秒）
     */
    private long[] calculateRepairOrderSuspensionTime(Long orderId) {
        // 从数据库中直接获取挂起时长记录
        int[] suspensionRecord = gxtOrderHourMapper.selectRepairOrderSuspensionTime(orderId);
        
        if (suspensionRecord != null && suspensionRecord.length >= 3) {
            // 数据库存储的是秒，需要转换为毫秒
            int beforeStartSeconds = suspensionRecord[0];  // 开工前挂起秒数
            int inWorkSeconds = suspensionRecord[1];       // 作业中挂起秒数
            int nightAutoSeconds = suspensionRecord[2];    // 夜间自动挂起秒数
            
            // 总挂起时长 = 开工前挂起 + 作业中挂起 + 夜间自动挂起
            long totalSuspensionTime = (long)(beforeStartSeconds + inWorkSeconds + nightAutoSeconds) * 1000;
            
            // 开工前挂起时长 = 开工前挂起 + 夜间自动挂起（夜间自动挂起也算作开工前）
            long beforeStartSuspensionTime = (long)(beforeStartSeconds + nightAutoSeconds) * 1000;
            
            // 开工后挂起时长 = 作业中挂起
            long afterStartSuspensionTime = (long)inWorkSeconds * 1000;
            
            return new long[]{totalSuspensionTime, beforeStartSuspensionTime, afterStartSuspensionTime};
        } else {
            // 如果没有找到记录，返回默认值
            return new long[]{0L, 0L, 0L};
        }
    }

    /**
     * 计算维保工单的挂起时长，分为开工前和开工后两部分
     * 维保工单挂起对应的actionType是approved，恢复对应的是restart
     * 自动挂起对应的actionType是auto_suspend，恢复对应的是auto_resume
     *
     * @param orderId 工单ID
     * @return 包含总挂起时长、开工前挂起时长、开工后挂起时长的数组，索引0为总时长，索引1为开工前时长，索引2为开工后时长（毫秒）
     */
    private long[] calculateWorkOrderSuspensionTime(Long orderId) {
        // 从数据库中直接获取挂起时长记录
        int[] suspensionRecord = gxtOrderHourMapper.selectWorkOrderSuspensionTime(orderId);
        
        if (suspensionRecord != null && suspensionRecord.length >= 3) {
            // 数据库存储的是秒，需要转换为毫秒
            int beforeStartSeconds = suspensionRecord[0];  // 开工前挂起秒数
            int inWorkSeconds = suspensionRecord[1];       // 作业中挂起秒数
            int nightAutoSeconds = suspensionRecord[2];    // 夜间自动挂起秒数
            
            // 总挂起时长 = 开工前挂起 + 作业中挂起 + 夜间自动挂起
            long totalSuspensionTime = (long)(beforeStartSeconds + inWorkSeconds + nightAutoSeconds) * 1000;
            
            // 开工前挂起时长 = 开工前挂起 + 夜间自动挂起（夜间自动挂起也算作开工前）
            long beforeStartSuspensionTime = (long)(beforeStartSeconds + nightAutoSeconds) * 1000;
            
            // 开工后挂起时长 = 作业中挂起
            long afterStartSuspensionTime = (long)inWorkSeconds * 1000;
            
            return new long[]{totalSuspensionTime, beforeStartSuspensionTime, afterStartSuspensionTime};
        } else {
            // 如果没有找到记录，返回默认值
            return new long[]{0L, 0L, 0L};
        }
    }

    /**
     * 计算工单详情中的各个时长（用于前端展示）
     * 
     * @param order 工单信息
     */
    public void calculateOrderTimeDetails(OrderScoreInfo order) {
        // 下发时长 = 下发时间 - 故障发生时间（维修工单）或创建时间（维保工单）
        if (order.getAssignTime() != null) {
            Date startTime = null;
            if (order.getOrderType() == 1) { // 维修工单
                startTime = order.getOccurTime();
            } else if (order.getOrderType() == 2) { // 维保工单
                startTime = order.getCreateTime();
            }
            
            if (startTime != null) {
                long diffMillis = order.getAssignTime().getTime() - startTime.getTime();
                order.setIssueHour(diffMillis / (1000.0 * 60 * 60));
            }
        }

        // 挂起时长 = 恢复时间 - 挂起时间
        long[] suspensionTimes = new long[3]; // 总挂起时长, 开工前挂起时长, 开工挂起后时长
        if (order.getOrderType() == 1) { // 维修工单
            suspensionTimes = calculateRepairOrderSuspensionTime(order.getId());
        } else if (order.getOrderType() == 2) { // 维保工单
            suspensionTimes = calculateWorkOrderSuspensionTime(order.getId());
        }

        // 设置各种挂起时长（转换为小时）
        order.setSuspendHour(suspensionTimes[0] / (1000.0 * 60 * 60));
        order.setBeforeStartSuspendHour(suspensionTimes[1] / (1000.0 * 60 * 60));
        order.setAfterStartSuspendHour(suspensionTimes[2] / (1000.0 * 60 * 60));

        // 接单时长 = 接单时间 – 下发时间 - 夜间工单的自动挂起时长
        // 计算接单期间的自动挂起时长（夜间工单挂起）
        long acceptSuspensionTime = 0;
        if (order.getAcceptTime() != null && order.getAssignTime() != null) {
            // 计算接单期间的自动挂起时长
            acceptSuspensionTime = calculateOrderAcceptSuspensionTime(order.getId(), order.getAssignTime(), order.getAcceptTime(), order.getOrderType());
            
            long diffMillis = order.getAcceptTime().getTime() - order.getAssignTime().getTime();
            order.setAcceptHour((diffMillis - acceptSuspensionTime) / (1000.0 * 60 * 60));
        }

        // 准备时长 = 开始打卡时间 – 接单时间 - 开工前挂起时长
        if (order.getRealStartTime() != null && order.getAcceptTime() != null) {
            //long diffMillis = order.getRealStartTime().getTime() - order.getAssignTime().getTime() - suspensionTimes[1] ;
            long diffMillis = order.getRealStartTime().getTime() - order.getAcceptTime().getTime() - suspensionTimes[1] ;
            order.setPrepareHour(diffMillis / (1000.0 * 60 * 60));
        }
        
        // 作业时长 = 结束打卡时间 - 开始打卡时间 - 开工后挂起时长
        if (order.getRealEndTime() != null && order.getRealStartTime() != null) {
            long diffMillis = order.getRealEndTime().getTime() - order.getRealStartTime().getTime() - suspensionTimes[2] ;
            order.setWorkHour(diffMillis / (1000.0 * 60 * 60));
        }
        
        // 验收时长 = 结束打卡时间 – 复运时间
        if (order.getRestartTime() != null && order.getRealEndTime() != null) {
            //long diffMillis = order.getRestartTime().getTime() - order.getRealEndTime().getTime();
            long diffMillis = order.getRealEndTime().getTime() - order.getRestartTime().getTime();
            order.setRestartHour(diffMillis / (1000.0 * 60 * 60));
        }

        // 处理时长 = 复运时间 – 故障发生时间（维修工单）或创建时间（维保工单） – 挂起时长
        /*double processingHours = calculateOrderProcessingHours(order);
        order.setHandleHour(processingHours);*/

        /*
        // 停运时长 = 复运时间 – 故障发生时间（维修工单）或创建时间（维保工单）
         Double originalDowntimeHour = null;
        if (order.getRestartTime() != null) {
            Date startTime = null;
            if (order.getOrderType() == 1) { // 维修工单
                startTime = order.getOccurTime();
            } else if (order.getOrderType() == 2) { // 维保工单
                startTime = order.getCreateTime();
            }

            if (startTime != null) {
                long diffMillis = order.getRestartTime().getTime() - startTime.getTime();
                originalDowntimeHour = diffMillis / (1000.0 * 60 * 60);
                order.setDowntimeHour(originalDowntimeHour);
            }
        }*/

        // 停运时长 = 复运时间 – 故障发生时间（维修工单）或停机时间（维保工单）
        Double originalDowntimeHour = null;
        if (order.getRestartTime() != null) {
            Date startTime = null;
            if (order.getOrderType() == 1) { // 维修工单
                startTime = order.getOccurTime();
            } else if (order.getOrderType() == 2) { // 维保工单
                startTime = order.getPauseTime();
            }

            if (startTime != null) {
                long diffMillis = order.getRestartTime().getTime() - startTime.getTime();
                originalDowntimeHour = diffMillis / (1000.0 * 60 * 60);
                order.setDowntimeHour(originalDowntimeHour);
            }
        }
        // 使用新方法计算停运时长：停运时长 = 下发时长 + 接单时长 + 准备时长 + 挂起时长 + 作业时长 + 验收时长
        // G(停运时长)=A(下发时长)+B(接单时长)+C(准备时长)+D(挂起时长)+E(作业时长)+F(验收时长)
        if (originalDowntimeHour != null) {
            Double newDowntimeHour = 0.0;
            
            // 累加各项时长
            if (order.getIssueHour() != null) {
                newDowntimeHour += order.getIssueHour();
            }
            if (order.getAcceptHour() != null) {
                newDowntimeHour += order.getAcceptHour();
            }
            if (order.getPrepareHour() != null) {
                newDowntimeHour += order.getPrepareHour();
            }
            if (order.getSuspendHour() != null) {
                newDowntimeHour += order.getSuspendHour();
            }
            if (order.getWorkHour() != null) {
                newDowntimeHour += order.getWorkHour();
            }
            if (order.getRestartHour() != null) {
                newDowntimeHour += order.getRestartHour();
            }
            
            // 比较两种计算结果，如果不相等则在控制台输出错误信息
            // 允许一定的精度误差（例如1毫秒）
            double tolerance = 1.0 / (1000 * 60 * 60); // 1毫秒的小时数
            double difference = Math.abs(newDowntimeHour - originalDowntimeHour);
            if (difference > tolerance) {
                log.error("停运时长计算不匹配！工单ID: " + order.getId() +
                                   ", 原始计算结果: " + String.format("%.6f", originalDowntimeHour) + 
                                   ", 新方法计算结果: " + String.format("%.6f", newDowntimeHour) + 
                                   ", 差值: " + String.format("%.6f", difference));
            }
        }

    }
    
    /**
     * 计算工单在指定时间段内的自动挂起时长
     * 
     * @param orderId 工单ID
     * @param startTime 段开始时间
     * @param endTime 段结束时间
     * @param orderType 工单类型：1为维修工单，2为维保工单
     * @return 自动挂起时长（毫秒）
     */
    private long calculateOrderAcceptSuspensionTime(Long orderId, Date startTime, Date endTime, int orderType) {
        if (startTime == null || endTime == null || startTime.after(endTime)) {
            return 0;
        }
        
        long suspensionTime = 0;
        Date suspendTime = null;
        
        if (orderType == 1) { // 维修工单
            List<GxtRepairOrderFlow> repairFlows = gxtRepairOrderFlowMapper.selectGxtRepairOrderFlowListByOrderId(orderId);
            
            // 按时间顺序处理流转记录
            repairFlows.sort((f1, f2) -> f1.getActionTime().compareTo(f2.getActionTime()));
            
            for (GxtRepairOrderFlow flow : repairFlows) {
                if ("auto_suspend".equals(flow.getActionType())) {
                    // 检查挂起时间是否在指定时间段内
                    if (flow.getActionTime().after(startTime) && flow.getActionTime().before(endTime)) {
                        suspendTime = flow.getActionTime();
                    }
                } else if ("auto_resume".equals(flow.getActionType()) && suspendTime != null) {
                    // 检查恢复时间是否在指定时间段内
                    if (flow.getActionTime().after(startTime) && flow.getActionTime().before(endTime)) {
                        long duration = flow.getActionTime().getTime() - suspendTime.getTime();
                        if (duration > 0) {
                            suspensionTime += duration;
                        }
                    }
                    suspendTime = null; // 重置挂起时间
                }
            }
        } else if (orderType == 2) { // 维保工单
            List<GxtWorkOrderFlow> workFlows = gxtWorkOrderFlowMapper.selectGxtWorkOrderFlowByOrderId(orderId);
            
            // 按时间顺序处理流转记录
            workFlows.sort((f1, f2) -> f1.getActionTime().compareTo(f2.getActionTime()));
            
            for (GxtWorkOrderFlow flow : workFlows) {
                if ("auto_suspend".equals(flow.getActionType())) {
                    // 检查挂起时间是否在指定时间段内
                    if (flow.getActionTime().after(startTime) && flow.getActionTime().before(endTime)) {
                        suspendTime = flow.getActionTime();
                    }
                } else if ("auto_resume".equals(flow.getActionType()) && suspendTime != null) {
                    // 检查恢复时间是否在指定时间段内
                    if (flow.getActionTime().after(startTime) && flow.getActionTime().before(endTime)) {
                        long duration = flow.getActionTime().getTime() - suspendTime.getTime();
                        if (duration > 0) {
                            suspensionTime += duration;
                        }
                    }
                    suspendTime = null; // 重置挂起时间
                }
            }
        }
        
        return suspensionTime;
    }
    
    /**
     * 计算工单的作业时长（用于统计和排名）
     * 作业时长 = 结束打卡时间 - 开始打卡时间 - 开工后挂起时长
     * 
     * @param order 工单信息
     * @return 作业时长（小时）
     */
    private double calculateWorkHours(OrderScoreInfo order) {
        if (order.getRealEndTime() == null || order.getRealStartTime() == null) {
            return 0;
        }
        
        // 计算挂起时长
        long[] suspensionTimes = new long[3]; // 总挂起时长, 开工前挂起时长, 开工挂起后时长
        if (order.getOrderType() == 1) { // 维修工单
            suspensionTimes = calculateRepairOrderSuspensionTime(order.getId());
        } else if (order.getOrderType() == 2) { // 维保工单
            suspensionTimes = calculateWorkOrderSuspensionTime(order.getId());
        }
        
        // 作业时长 = 结束打卡时间 - 开始打卡时间 - 开工后挂起时长
        long diffMillis = order.getRealEndTime().getTime() - order.getRealStartTime().getTime() - suspensionTimes[2];
        return diffMillis / (1000.0 * 60 * 60);
    }

    /**
     * 获取工单工时统计信息
     *
     * @param repairOrder 维修工单查询条件
     * @param workOrder 维保工单查询条件
     * @param orderType 工单类型筛选条件
     * @param timeRange 时间范围参数 (week:本周, month:本月, custom:自定义)
     * @param beginDate 自定义开始时间
     * @param endDate 自定义结束时间
     * @param keyword 搜索关键字
     * @return 统计信息
     */
    public Map<String, Object> getOrderHourStatisticsV0(GxtRepairOrder repairOrder, GxtWorkOrder workOrder, String orderType, String timeRange, String beginDate, String endDate, String keyword) {
        // 处理时间范围参数
        processTimeRange(repairOrder, workOrder, timeRange, beginDate, endDate);

        // 添加业务特定的数据权限过滤
        addBusinessDataScopeFilter(repairOrder, workOrder);

        // 设置创建人，用于数据权限过滤
        if(!Constants.SUPER_ADMIN.equals(SecurityUtils.getUsername())){
            if (repairOrder.getCreateBy() == null || repairOrder.getCreateBy().isEmpty()) {
                repairOrder.setCreateBy(SecurityUtils.getUsername());
            }

            if (workOrder.getCreateBy() == null || workOrder.getCreateBy().isEmpty()) {
                workOrder.setCreateBy(SecurityUtils.getUsername());
            }
        }

        // 获取统计数据
        List<OrderScoreInfo> orderList = gxtOrderHourMapper.selectUnionOrderList(repairOrder, workOrder, orderType, keyword);

        // 计算统计信息
        Map<String, Object> statistics = new HashMap<>();

        double totalHours = 0;
        double maintenanceHours = 0;
        double repairHours = 0;
        int maintenanceCount = 0;
        int repairCount = 0;

        for (OrderScoreInfo order : orderList) {
            // 使用专门计算作业时长的方法
            double hours = calculateWorkHours(order);
            totalHours += hours;

            if (order.getOrderType() == 2) { // 维保工单
                maintenanceHours += hours;
                maintenanceCount++;
            } else if (order.getOrderType() == 1) { // 维修工单
                repairHours += hours;
                repairCount++;
            }
        }

        statistics.put("totalHours", totalHours);
        statistics.put("maintenanceHours", maintenanceHours);
        statistics.put("repairHours", repairHours);
        statistics.put("maintenanceCount", maintenanceCount);
        statistics.put("repairCount", repairCount);
        statistics.put("orderCount", orderList.size());

        // 如果用户的数据权限是"仅本人数据"，则计算排名
        if (isCurrentUserDataScopeSelf()) {
            int rank = calculateUserRankInStation(repairOrder, workOrder, orderType, timeRange, beginDate, endDate, keyword);
            statistics.put("rank", rank);

            // 计算场站总人数
            LoginUser loginUser = SecurityUtils.getLoginUser();
            if (loginUser != null && loginUser.getUser() != null) {
                Long deptId = loginUser.getUser().getDeptId();
                if (deptId != null) {
                    int totalUsersInStation = getStationUserIds(deptId).size();
                    statistics.put("totalRankingUsers", totalUsersInStation);
                }
            }
        }

        return statistics;
    }

    /**
     * 计算维修工单的挂起时长，分为开工前和开工后两部分
     * 维修工单挂起对应的actionType是approved，恢复对应的是resume
     * 自动挂起对应的actionType是auto_suspend，恢复对应的是auto_resume
     *
     * @param orderId 工单ID
     * @return 包含总挂起时长、开工前挂起时长、开工后挂起时长的数组，索引0为总时长，索引1为开工前时长，索引2为开工后时长（毫秒）
     */
    private long[] calculateRepairOrderSuspensionTimeV0(Long orderId) {
        GxtRepairOrder order = gxtRepairOrderService.selectGxtRepairOrderById(orderId);
        List<GxtRepairOrderFlow> flows = gxtRepairOrderFlowMapper.selectGxtRepairOrderFlowListByOrderId(orderId);
        Date realStartTime = order.getRealStartTime();
        long totalSuspensionTime = 0;
        long beforeStartSuspensionTime = 0;
        long afterStartSuspensionTime = 0;
        Date suspendTime = null;
        GxtRepairOrderFlow suspendFlow = null;
        // 按时间顺序处理流转记录
        flows.sort((f1, f2) -> f1.getActionTime().compareTo(f2.getActionTime()));

        for (GxtRepairOrderFlow flow : flows) {
            if ("approved".equals(flow.getActionType()) || "auto_suspend".equals(flow.getActionType())) {
                suspendFlow = flow;
                // 挂起时间
                suspendTime = flow.getActionTime();
            } else if (("resume".equals(flow.getActionType()) || "auto_resume".equals(flow.getActionType())) && suspendTime != null) {
                // 恢复时间
                long suspensionDuration = flow.getActionTime().getTime() - suspendTime.getTime();
                //totalSuspensionTime += suspensionDuration;

                // 判断是开工前还是开工后挂起
                Date realEndTime = order.getRealEndTime();
                if (realStartTime != null && realEndTime != null) {
                    // 计算实际有效的挂起时间段
                    Date effectiveSuspendStart = suspendTime;
                    Date effectiveSuspendEnd = flow.getActionTime();

                    // 如果挂起时间早于开工时间
                    if (suspendTime.before(realStartTime)) {
                        // 挂起时间到开工时间这段时间算为开工前挂起
                        Date overlapEnd = effectiveSuspendEnd.before(realStartTime) ? effectiveSuspendEnd : realStartTime;
                        long beforeStartDuration = overlapEnd.getTime() - effectiveSuspendStart.getTime();
                        if (beforeStartDuration > 0) {
                            beforeStartSuspensionTime += beforeStartDuration;
                        }

                        // 剩余部分如果在开工后结束时间前，则算作开工后挂起
                        if (effectiveSuspendEnd.after(realStartTime) && effectiveSuspendEnd.before(realEndTime)) {
                            Date overlapStart = effectiveSuspendStart.after(realStartTime) ? effectiveSuspendStart : realStartTime;
                            long afterStartDuration = effectiveSuspendEnd.getTime() - overlapStart.getTime();
                            if (afterStartDuration > 0) {
                                afterStartSuspensionTime += afterStartDuration;
                            }
                        }
                    } else {
                        // 挂起时间在开工时间之后
                        if("auto_suspend".equals(suspendFlow.getActionType())){
                            // 自动挂起仍然算作开工前挂起
                            beforeStartSuspensionTime += suspensionDuration;
                        } else {
                            // 普通挂起，只计算在开工时间到结束时间范围内的部分
                            if (effectiveSuspendStart.before(realEndTime)) {
                                Date actualEnd = effectiveSuspendEnd.before(realEndTime) ? effectiveSuspendEnd : realEndTime;
                                long validDuration = actualEnd.getTime() - effectiveSuspendStart.getTime();
                                if (validDuration > 0) {
                                    afterStartSuspensionTime += validDuration;
                                }
                            }
                        }
                    }
                } else {
                    // 如果没有开工时间，默认全部算作开工前挂起
                    beforeStartSuspensionTime += suspensionDuration;
                }

                suspendTime = null; // 重置挂起时间
                suspendFlow = null;
            }
        }
        totalSuspensionTime = beforeStartSuspensionTime + afterStartSuspensionTime;
        return new long[]{totalSuspensionTime, beforeStartSuspensionTime, afterStartSuspensionTime};
    }

    /**
     * 计算维保工单的挂起时长，分为开工前和开工后两部分
     * 维保工单挂起对应的actionType是approved，恢复对应的是restart
     * 自动挂起对应的actionType是auto_suspend，恢复对应的是auto_resume
     *
     * @param orderId 工单ID
     * @return 包含总挂起时长、开工前挂起时长、开工后挂起时长的数组，索引0为总时长，索引1为开工前时长，索引2为开工后时长（毫秒）
     */
    private long[] calculateWorkOrderSuspensionTimeV0(Long orderId) {
        GxtWorkOrder order = gxtWorkOrderService.selectGxtWorkOrderById(orderId);
        List<GxtWorkOrderFlow> flows = gxtWorkOrderFlowMapper.selectGxtWorkOrderFlowByOrderId(orderId);
        Date realStartTime = order.getRealStartTime();
        long totalSuspensionTime = 0;
        long beforeStartSuspensionTime = 0;
        long afterStartSuspensionTime = 0;
        Date suspendTime = null;
        GxtWorkOrderFlow suspendFlow = null;

        // 按时间顺序处理流转记录
        flows.sort((f1, f2) -> f1.getActionTime().compareTo(f2.getActionTime()));

        for (GxtWorkOrderFlow flow : flows) {
            if ("approved".equals(flow.getActionType()) || "auto_suspend".equals(flow.getActionType())) {
                suspendFlow = flow;
                // 挂起时间
                suspendTime = flow.getActionTime();
            } else if (("resume".equals(flow.getActionType()) || "auto_resume".equals(flow.getActionType())) && suspendTime != null) {
                // 恢复时间
                long suspensionDuration = flow.getActionTime().getTime() - suspendTime.getTime();
                //totalSuspensionTime += suspensionDuration;

                // 判断是开工前还是开工后挂起
                Date realEndTime = order.getRealEndTime();
                if (realStartTime != null && realEndTime != null) {
                    // 计算实际有效的挂起时间段
                    Date effectiveSuspendStart = suspendTime;
                    Date effectiveSuspendEnd = flow.getActionTime();

                    // 如果挂起时间早于开工时间
                    if (suspendTime.before(realStartTime)) {
                        // 挂起时间到开工时间这段时间算为开工前挂起
                        Date overlapEnd = effectiveSuspendEnd.before(realStartTime) ? effectiveSuspendEnd : realStartTime;
                        long beforeStartDuration = overlapEnd.getTime() - effectiveSuspendStart.getTime();
                        if (beforeStartDuration > 0) {
                            beforeStartSuspensionTime += beforeStartDuration;
                        }

                        // 剩余部分如果在开工后结束时间前，则算作开工后挂起
                        if (effectiveSuspendEnd.after(realStartTime) && effectiveSuspendEnd.before(realEndTime)) {
                            Date overlapStart = effectiveSuspendStart.after(realStartTime) ? effectiveSuspendStart : realStartTime;
                            long afterStartDuration = effectiveSuspendEnd.getTime() - overlapStart.getTime();
                            if (afterStartDuration > 0) {
                                afterStartSuspensionTime += afterStartDuration;
                            }
                        }
                    } else {
                        // 挂起时间在开工时间之后
                        if("auto_suspend".equals(suspendFlow.getActionType())){
                            // 自动挂起仍然算作开工前挂起
                            beforeStartSuspensionTime += suspensionDuration;
                        } else {
                            // 普通挂起，只计算在开工时间到结束时间范围内的部分
                            if (effectiveSuspendStart.before(realEndTime)) {
                                Date actualEnd = effectiveSuspendEnd.before(realEndTime) ? effectiveSuspendEnd : realEndTime;
                                long validDuration = actualEnd.getTime() - effectiveSuspendStart.getTime();
                                if (validDuration > 0) {
                                    afterStartSuspensionTime += validDuration;
                                }
                            }
                        }
                    }
                } else {
                    // 如果没有开工时间，默认全部算作开工前挂起
                    beforeStartSuspensionTime += suspensionDuration;
                }

                suspendTime = null; // 重置挂起时间
                suspendFlow = null;
            }
        }
        totalSuspensionTime = beforeStartSuspensionTime + afterStartSuspensionTime;
        return new long[]{totalSuspensionTime, beforeStartSuspensionTime, afterStartSuspensionTime};
    }
}