package cn.iocoder.yudao.module.pms.job.dailyreport;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.pms.constant.PmsConstants;
import cn.iocoder.yudao.module.pms.controller.admin.iotryimprovedailyreport.vo.IotRyImproveDailyReportPageReqVO;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotryimprovedailyreport.IotRyImproveDailyReportDO;
import cn.iocoder.yudao.module.pms.dal.mysql.iotryimprovedailyreport.IotRyImproveDailyReportMapper;
import cn.iocoder.yudao.module.pms.message.PmsMessage;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;

/**
 * 瑞鹰 项目启动设备整改 日报定时任务
 * 每天 22:00 生成日报
 */
@Component
@Slf4j
public class CreateRyImproveDailyReportOrderJob implements JobHandler {
    @Resource
    private AdminUserApi adminUserApi;

    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;
    @Resource
    private PmsMessage pmsMessage;
    @Resource
    private DeptService deptService;

    @Resource
    private DictDataService dictDataService;
    @Resource
    private AdminUserService adminUserService;
    @Resource
    private RoleService roleService;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private IotRyImproveDailyReportMapper iotRyImproveDailyReportMapper;

    @Override
    @TenantIgnore
    public String execute(String param) throws Exception {
        // 查询数据字典中 需要生成 瑞鹰项目启动设备整改 日报的部门
        // 筛选部门下具有 角色 '项目启动设备整改RY' 的 人员 设置为 日报的创建人
        // 修井 施工状态 字典数据
        Set<Long> departmentIds = new HashSet<>();
        List<DictDataDO> improveReportDeptDictData = dictDataService.getDictDataListByDictType("rq_iot_improve_report_dept");
        if (CollUtil.isNotEmpty(improveReportDeptDictData)) {
            improveReportDeptDictData.forEach(data -> {
                departmentIds.add(Long.valueOf(data.getValue()));
            });
        }

        if (CollUtil.isNotEmpty(departmentIds)) {
            Set<Long> projectDeptIds = new HashSet<>();
            projectDeptIds.addAll(departmentIds);
            List<AdminUserDO> receivedMsgUsers = adminUserService.getUserListByDeptIds(projectDeptIds);
            Set<Long> userIds = new HashSet<>();
            if (CollUtil.isNotEmpty(receivedMsgUsers)) {
                receivedMsgUsers.forEach(user -> {
                    userIds.add(user.getId());
                });
            }
            RoleDO role = roleService.getRoleByCode("项目启动设备整改RY");
            if (ObjUtil.isNotEmpty(role)) {
                Set<Long> roleIds = new HashSet<>();
                roleIds.add(role.getId());
                List<UserRoleDO> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
                if (CollUtil.isNotEmpty(userRoles)) {
                    // 提取有审批角色的所有用户ID（去重+空值过滤）
                    Set<Long> roleUserIds = userRoles.stream()
                            .map(UserRoleDO::getUserId)
                            .filter(Objects::nonNull) // 过滤空userId
                            .collect(Collectors.toSet());
                    // 计算两个集合的交集，得到最终目标用户ID
                    Set<Long> targetUserIds = userIds.stream()
                            .filter(roleUserIds::contains)
                            .collect(Collectors.toSet());
                    // 从 targetUserIds 随机选择1个用户作为日报的 创建人
                    List<Long> targetUserIdList = new ArrayList<>(targetUserIds);
                    if (CollUtil.isNotEmpty(targetUserIdList)) {
                        Long creatorId = targetUserIdList.get(0);
                        // 当天已经生成 瑞鹰项目启动设备整改 日报的队伍deptId集合
                        Set<Long> currentDayReportedDeptIds = new HashSet<>();
                        // 查询所有 '瑞鹰项目启动设备整改日报' 以‘部门-时间’ 为唯一键 当天创建时间 内没有生成过日报
                        LocalDateTime currentDate = LocalDateTime.now();
                        String currentFormatDateStr = LocalDateTimeUtil.format(currentDate, "yyyy-MM-dd");
                        IotRyImproveDailyReportPageReqVO ryReqVO = new IotRyImproveDailyReportPageReqVO();
                        ryReqVO.setDeptIds(departmentIds);
                        ryReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
                        PageResult<IotRyImproveDailyReportDO> pageReports = iotRyImproveDailyReportMapper.selectPage(ryReqVO);
                        if (ObjUtil.isNotEmpty(pageReports)) {
                            List<IotRyImproveDailyReportDO> improveDailyReports = pageReports.getList();
                            if (CollUtil.isNotEmpty(improveDailyReports)) {
                                improveDailyReports.forEach(report -> {
                                    // 查询当天生成的日报
                                    LocalDateTime createDate = report.getCreateTime();
                                    String formatDateStr = LocalDateTimeUtil.format(createDate, "yyyy-MM-dd");
                                    if (formatDateStr.equals(currentFormatDateStr)) {
                                        currentDayReportedDeptIds.add(report.getDeptId());
                                    }
                                });
                            }
                        }
                        // 如果当天的 瑞鹰项目启动设备整改 日报记录中不包含 数据字典中配置的部门id 则生成队伍日报记录
                        Set<Long> tobeReportDeptIds = departmentIds.stream()
                                .filter(deptId -> !currentDayReportedDeptIds.contains(deptId))
                                .collect(Collectors.toSet());
                        List<IotRyImproveDailyReportDO> tobeAddedReports = new ArrayList<>();
                        if (CollUtil.isNotEmpty(tobeReportDeptIds)) {
                            // 查询这些部门对象集合
                            Map<Long, DeptDO> deptMap = deptService.getDeptMap(tobeReportDeptIds);
                            for (Long tobeReportDeptId : tobeReportDeptIds) {
                                IotRyImproveDailyReportDO improveReport = new IotRyImproveDailyReportDO();
                                improveReport.setDeptId(tobeReportDeptId);
                                improveReport.setStatus(0);
                                improveReport.setAuditStatus(0);
                                improveReport.setCreateTime(LocalDateTime.now());
                                improveReport.setCreator(creatorId.toString());
                                tobeAddedReports.add(improveReport);
                            }
                            if (CollUtil.isNotEmpty(tobeAddedReports)) {
                                iotRyImproveDailyReportMapper.insertBatch(tobeAddedReports);

                                // 异步发送消息提醒 钉钉 站内信
                                // 查询所有日报的创建人 userId 集合
                                Set<Long> msgUserIds = new HashSet<>(convertList(tobeAddedReports, report -> Long.valueOf(report.getCreator())));
                                Map<Long, AdminUserRespDTO> users = adminUserApi.getUserMap(msgUserIds);
                                // 建立日报与 用户手机号的 对应关系
                                Map<Long, String> reportMobilePair = new HashMap<>();
                                tobeAddedReports.forEach(report -> {
                                    if (users.containsKey(Long.valueOf(report.getCreator()))) {
                                        AdminUserRespDTO user = users.get(Long.valueOf(report.getCreator()));
                                        reportMobilePair.put(report.getId(), user.getMobile());
                                    }
                                });
                                // 异步多线程发送 站内信 钉钉 消息
                                tobeAddedReports.forEach(report -> {
                                    CountDownLatch latch = new CountDownLatch(tobeAddedReports.size());
                                    // deptMap 部门集合   taskWellNamePair任务集合
                                    Long deptId = report.getDeptId();
                                    DeptDO dept = deptMap.get(deptId);
                                    String msgTitle = dept.getName();
                                    String finalMsgTitle = msgTitle;
                                    pmsThreadPoolTaskExecutor.execute(() -> {
                                        try {
                                            // 用户 没有维护 手机号 也可以发送站内信消息
                                            String mobile = StrUtil.EMPTY;
                                            if (reportMobilePair.containsKey(report.getId())) {
                                                mobile = reportMobilePair.get(report.getId());
                                            }
                                            pmsMessage.sendMessage(report.getId(), finalMsgTitle, PmsConstants.RY_XJ_DAILY_REPORT,
                                                    Long.valueOf(report.getCreator()), mobile);
                                        } finally {
                                            latch.countDown();
                                        }
                                    });
                                });
                            }
                        }
                    }
                }
            }
        }
        return "创建成功";
    }
}
