package com.ygtx.gxt.task;

import com.ygtx.common.core.domain.entity.SysUser;
import com.ygtx.common.core.domain.model.LoginUser;
import com.ygtx.common.utils.DateUtils;
import com.ygtx.framework.web.service.SysPermissionService;
import com.ygtx.gxt.domain.*;
import com.ygtx.gxt.service.IGxtOrderScoreService;
import com.ygtx.gxt.service.IGxtRepairOrderFlowService;
import com.ygtx.gxt.service.IGxtRepairOrderService;
import com.ygtx.gxt.service.IGxtWorkOrderFlowService;
import com.ygtx.gxt.service.IGxtWorkOrderService;
import com.ygtx.system.mapper.SysUserMapper;
import com.ygtx.system.service.ISysConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 维修工单自动复评任务
 * 每小时执行，对自评超过24小时但未复评的维修工单和维保工单进行自动复评
 *
 * @author ouyj
 * @date 2026-01-06
 */
@EnableScheduling
@Component("orderScoreAutoReviewTask")
public class OrderScoreAutoReviewTask {

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

    @Autowired
    private IGxtRepairOrderService repairOrderService;

    @Autowired
    private IGxtRepairOrderFlowService repairOrderFlowService;

    @Autowired
    private IGxtWorkOrderService workOrderService;

    @Autowired
    private IGxtWorkOrderFlowService workOrderFlowService;

    @Autowired
    private IGxtOrderScoreService orderScoreService;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private ISysConfigService configService;

    /**
     * 每小时执行定时任务
     * 查找自评超过24小时但未复评的维修工单和维保工单，并进行自动复评
     */
    //@Scheduled(cron = "0 0 * * * ?") // 每小时执行一次
    // @Scheduled(cron = "0 */5 * * * ?") // 每5分钟执行一次 - 用于测试
    public void autoReviewOrders() {
        log.info("开始执行工单自动复评任务");
        
        // 设置系统用户上下文
        setSystemUserContext();
        
        try {
            // 处理维修工单的自动复评
            processRepairOrders();

            // 处理维保工单的自动复评
            processWorkOrders();

        } catch (Exception e) {
            log.error("执行工单自动复评任务时发生异常", e);
        }
    }

    /**
     * 处理维修工单的自动复评
     */
    private void processRepairOrders() {
        try {
            // 构造查询条件：自评状态的工单
            GxtRepairOrder queryOrder = new GxtRepairOrder();
            queryOrder.setWorkOrderStatus("completed");
            queryOrder.setScoringStatus("to_re"); // 待复评状态
            List<GxtRepairOrder> orders = repairOrderService.selectGxtRepairOrderList(queryOrder);

            int reviewCount = 0;
            for (GxtRepairOrder order : orders) {
                // 检查是否满足自动复评条件（自评超过24小时）
                if (shouldAutoReviewRepairOrder(order)) {
                    // 执行自动复评操作
                    autoReviewRepairOrder(order);
                    reviewCount++;
                }
            }

            log.info("维修工单自动复评任务执行完成，共处理 {} 个工单", reviewCount);
        } catch (Exception e) {
            log.error("处理维修工单自动复评时发生异常", e);
        }
    }

    /**
     * 处理维保工单的自动复评
     */
    private void processWorkOrders() {
        try {
            // 构造查询条件：待复评状态的维保工单
            GxtWorkOrder queryOrder = new GxtWorkOrder();
            queryOrder.setWorkOrderStatus("completed");
            queryOrder.setScoringStatus("to_re"); // 待复评状态
            List<GxtWorkOrder> orders = workOrderService.selectGxtWorkOrderList(queryOrder);

            int reviewCount = 0;
            for (GxtWorkOrder order : orders) {
                // 检查是否满足自动复评条件（自评超过24小时）
                if (shouldAutoReviewWorkOrder(order)) {
                    // 执行自动复评操作
                    autoReviewWorkOrder(order);
                    reviewCount++;
                }
            }

            log.info("维保工单自动复评任务执行完成，共处理 {} 个工单", reviewCount);
        } catch (Exception e) {
            log.error("处理维保工单自动复评时发生异常", e);
        }
    }

    /**
     * 判断维修工单是否满足自动复评条件
     * 条件：自评时间已超过配置的小时数，默认24小时
     *
     * @param order 维修工单
     * @return 是否满足自动复评条件
     */
    private boolean shouldAutoReviewRepairOrder(GxtRepairOrder order) {
        Date selfRatingTime = null;
        
        // 通过查询工单流转记录获取自评时间
        GxtRepairOrderFlow flowQuery = new GxtRepairOrderFlow();
        flowQuery.setOrderId(order.getId());
        flowQuery.setActionType("selfRating"); // 自评操作类型
        List<GxtRepairOrderFlow> flows = repairOrderFlowService.selectGxtRepairOrderFlowList(flowQuery);

        if (!flows.isEmpty()) {
            // 获取最后一次自评的时间
            selfRatingTime = flows.get(flows.size() - 1).getActionTime();
        }

        if (selfRatingTime == null) {
            return false;
        }

        // 从配置中获取自评超时小时数，如果配置为空则默认24小时
        String hoursStr = configService.selectConfigByKey("gxt.orderScore.autoReviewHours");
        int reviewHours = 24; // 默认24小时
        if (hoursStr != null && !hoursStr.trim().isEmpty()) {
            try {
                reviewHours = Integer.parseInt(hoursStr.trim());
            } catch (NumberFormatException e) {
                log.warn("配置的自动复评小时数不是有效数字，使用默认值24小时: {}", hoursStr);
            }
        }

        // 检查自评时间是否已超过配置的小时数
        Date now = DateUtils.getNowDate();
        Date reviewTimeThreshold = DateUtils.addHours(selfRatingTime, reviewHours);

        return now.after(reviewTimeThreshold);
    }

    /**
     * 判断维保工单是否满足自动复评条件
     * 条件：自评时间已超过配置的小时数，默认24小时
     *
     * @param order 维保工单
     * @return 是否满足自动复评条件
     */
    private boolean shouldAutoReviewWorkOrder(GxtWorkOrder order) {
        Date selfRatingTime = null;
        
        // 通过查询工单流转记录获取自评时间
        GxtWorkOrderFlow flowQuery = new GxtWorkOrderFlow();
        flowQuery.setOrderId(order.getId());
        flowQuery.setActionType("selfRating"); // 自评操作类型
        List<GxtWorkOrderFlow> flows = workOrderFlowService.selectGxtWorkOrderFlowList(flowQuery);

        if (!flows.isEmpty()) {
            // 获取最后一次自评的时间
            selfRatingTime = flows.get(flows.size() - 1).getActionTime();
        }

        if (selfRatingTime == null) {
            return false;
        }

        // 从配置中获取自评超时小时数，如果配置为空则默认24小时
        String hoursStr = configService.selectConfigByKey("gxt.orderScore.autoReviewHours");
        int reviewHours = 24; // 默认24小时
        if (hoursStr != null && !hoursStr.trim().isEmpty()) {
            try {
                reviewHours = Integer.parseInt(hoursStr.trim());
            } catch (NumberFormatException e) {
                log.warn("配置的自动复评小时数不是有效数字，使用默认值24小时: {}", hoursStr);
            }
        }

        // 检查自评时间是否已超过配置的小时数
        Date now = DateUtils.getNowDate();
        Date reviewTimeThreshold = DateUtils.addHours(selfRatingTime, reviewHours);

        return now.after(reviewTimeThreshold);
    }

    /**
     * 对维修工单进行自动复评操作
     *
     * @param order 需要复评的工单
     */
    private void autoReviewRepairOrder(GxtRepairOrder order) {
        try {
            // 获取工单的人员评分信息
            List<GxtRepairOrderPerson> orderPersons = repairOrderService.selectRepairOrderPersonListByOrderId(order.getId());
            
            // 创建评分信息对象
            OrderScoreInfo orderScoreInfo = new OrderScoreInfo();
            orderScoreInfo.setId(order.getId());
            orderScoreInfo.setOrderType(1); // 维修工单
            orderScoreInfo.setWorkOrderProjectNo(order.getWorkOrderProjectNo());
            
            // 复制原工单的评分状态和类型信息
            orderScoreInfo.setMaintenanceType(order.getMaintenanceType());
            orderScoreInfo.setFinalCoefficient(BigDecimal.ONE); // 系数设为1
            orderScoreInfo.setReviewScoreNum(order.getReviewScoreNum()+1);
            // 设置复运时间，用于在复评服务中正确判断状态转换
            //orderScoreInfo.setRestartTime(order.getRestartTime());
            
            // 设置人员评分列表
            if (orderPersons != null && !orderPersons.isEmpty()) {
                List<OrderScorePerson> scorePersons = orderPersons.stream().map(person -> {
                    OrderScorePerson scorePerson = new OrderScorePerson();
                    scorePerson.setId(person.getId());
                    scorePerson.setUserId(person.getUserId());
                    scorePerson.setNickName(person.getNickName());
                    
                    // 使用自评分作为复评分和总评分
                    Double selfScore = person.getSelfScore();
                    scorePerson.setReviewScore(selfScore);

                    Double totalScore = (person.getTotalScore() != null) ? person.getTotalScore() : selfScore;
                    scorePerson.setTotalScore(totalScore != null ? totalScore : 0.0);
                    
                    return scorePerson;
                }).collect(Collectors.toList());
                
                orderScoreInfo.setScorePersonList(scorePersons);
            } else {
                // 如果没有人员评分信息，则创建一个空列表，避免空指针异常
                orderScoreInfo.setScorePersonList(new ArrayList<>());
            }

            // 调用现有的复评方法
            int result = orderScoreService.review(orderScoreInfo);
            
            if (result > 0) {
                log.info("工单 {} 已成功自动复评", order.getWorkOrderProjectNo());
            } else {
                log.warn("工单 {} 自动复评失败", order.getWorkOrderProjectNo());
            }
        } catch (Exception e) {
            log.error("自动复评工单 {} 时发生异常", order.getWorkOrderProjectNo(), e);
        }
    }

    /**
     * 对维保工单进行自动复评操作
     *
     * @param order 需要复评的工单
     */
    private void autoReviewWorkOrder(GxtWorkOrder order) {
        try {
            // 获取工单的人员评分信息
            List<GxtWorkOrderPerson> orderPersons = workOrderService.selectWorkOrderPersonListByOrderId(order.getId());
            
            // 创建评分信息对象
            OrderScoreInfo orderScoreInfo = new OrderScoreInfo();
            orderScoreInfo.setId(order.getId());
            orderScoreInfo.setOrderType(2); // 维保工单
            orderScoreInfo.setWorkOrderProjectNo(order.getWorkOrderProjectNo());
            
            // 复制原工单的评分状态和类型信息
            orderScoreInfo.setInspectionType(order.getInspectionType());
            orderScoreInfo.setItemCompletionFactor(order.getItemCompletionFactor()); // 系数设为1
            orderScoreInfo.setReviewScoreNum(order.getReviewScoreNum()+1);
            
            // 设置人员评分列表
            if (orderPersons != null && !orderPersons.isEmpty()) {
                List<OrderScorePerson> scorePersons = orderPersons.stream().map(person -> {
                    OrderScorePerson scorePerson = new OrderScorePerson();
                    scorePerson.setId(person.getId());
                    scorePerson.setUserId(person.getUserId());
                    scorePerson.setNickName(person.getNickName());
                    
                    // 使用自评分作为复评分和总评分
                    Double selfScore = person.getSelfScore();
                    scorePerson.setReviewScore(selfScore);

                    Double totalScore = (person.getTotalScore() != null) ? person.getTotalScore() : selfScore;
                    scorePerson.setTotalScore(totalScore != null ? totalScore : 0.0);
                    
                    return scorePerson;
                }).collect(Collectors.toList());
                
                orderScoreInfo.setScorePersonList(scorePersons);
            } else {
                // 如果没有人员评分信息，则创建一个空列表，避免空指针异常
                orderScoreInfo.setScorePersonList(new ArrayList<>());
            }

            // 调用现有的复评方法
            int result = orderScoreService.review(orderScoreInfo);
            
            if (result > 0) {
                log.info("工单 {} 已成功自动复评", order.getWorkOrderProjectNo());
            } else {
                log.warn("工单 {} 自动复评失败", order.getWorkOrderProjectNo());
            }
        } catch (Exception e) {
            log.error("自动复评工单 {} 时发生异常", order.getWorkOrderProjectNo(), e);
        }
    }

    /**
     * 设置系统用户上下文，用于自动操作
     */
    private void setSystemUserContext() {
        try {
            // 获取admin用户信息
            SysUser userAdmin = userMapper.selectUserByUserName("admin");
            if (userAdmin != null) {
                Set<String> permissions = permissionService.getMenuPermission(userAdmin);
                LoginUser loginUser = new LoginUser(userAdmin, permissions);

                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                        loginUser,
                        null,
                        loginUser.getAuthorities()
                );

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception e) {
            log.error("设置系统用户上下文失败", e);
        }
    }
}