package cn.iocoder.yudao.module.smartfactory.framework.job.staffCertificateInformation;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.Constants;
import cn.iocoder.yudao.framework.common.enums.SocialTypeEnum;
import cn.iocoder.yudao.framework.common.template.WxMpMsgTemplateUtils;
import cn.iocoder.yudao.framework.common.template.dto.StaffCertificateInformationDTO;
import cn.iocoder.yudao.framework.common.template.vo.SubscribeMessageReqDTO;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staff.StaffDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffcertificateinformation.StaffCertificateInformationDO;
import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService;
import cn.iocoder.yudao.module.smartfactory.service.staffcertificateinformation.StaffCertificateInformationService;
import cn.iocoder.yudao.module.system.api.auth.AdminOauthUserOtherInfoApi;
import cn.iocoder.yudao.module.system.api.auth.dto.AdminOauthUserOtherInfoApiDTO;
import cn.iocoder.yudao.module.system.api.auth.vo.AdminOauthUserOtherInfoApiVO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 员工证件过期提醒 工厂负责人 - 每天下午3点执行 过期前3个月就提醒下
 */
@Component
@Slf4j
public class StaffCertificateInformationJob {

    @Resource
    private StaffCertificateInformationService staffCertificateInformationService;
    @Resource
    private StaffService staffService;
    @Resource
    private DeptApi deptApi;
    @Resource
    private AdminOauthUserOtherInfoApi adminOauthUserOtherInfoApi;

    @Resource
    private SubscribeMessageSendApi subscribeMessageSendApi;
    private static final String CERTIFICATE_NAME = "叉车年检信息";
    private static final String REMARKS = "的叉车年检信息即将到期，请注意!";

    @XxlJob("staffCertificateInformationJob")
    @TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
    public ReturnT<String> execute() throws Exception {
        LocalDateTime now = LocalDateTime.now();
        now = now.plusMonths(3L);
        // 获取当前日期 上个月得第一天
        List<StaffCertificateInformationDO> list = staffCertificateInformationService.list(new LambdaQueryWrapper<StaffCertificateInformationDO>()
                .eq(StaffCertificateInformationDO::getReminderFlag, 0)
                .le(StaffCertificateInformationDO::getForkliftAnnualInspectionExpiredTime, now));
        if (CollUtil.isEmpty(list)) {
            return ReturnT.SUCCESS;
        }
        List<Long> ids = list.stream().map(StaffCertificateInformationDO::getId).collect(Collectors.toList());

        Map<Long, LocalDateTime> forkliftAnnualInspectionExpiredTimeMap = list.stream().collect(Collectors.toMap(StaffCertificateInformationDO::getStaffId, StaffCertificateInformationDO::getForkliftAnnualInspectionExpiredTime));
        // 获取员工id 列表
        List<Long> staffIds = list.stream().map(StaffCertificateInformationDO::getStaffId).collect(Collectors.toList());
        // 查询员工列表 - 员工列表里面有工厂id 然后拿到工厂id 去查询部门表 获取到工厂负责人
        List<StaffDO> staffList = staffService.getList(staffIds);
        //根据工厂id分组
        Map<Long, List<StaffDO>> map = staffList.stream().collect(Collectors.groupingBy(StaffDO::getFactoryId));
        List<Long> factoryIds = new ArrayList<>(map.keySet());
        // 查询部门表根据工厂ids
        List<DeptRespDTO> deptList = deptApi.getDeptByFactoryIds(factoryIds).getCheckedData();
        //工厂负责人map
        Map<Long, Long> factoryLeaderUserIdMap = new HashMap<>();
        if (CollUtil.isEmpty(deptList)) {
            factoryLeaderUserIdMap = deptList.stream().collect(Collectors.toMap(DeptRespDTO::getFactoryId, DeptRespDTO::getLeaderUserId));
        }

        if (MapUtil.isNotEmpty(factoryLeaderUserIdMap)) {
            // -- 获取发起人的openId
            List<AdminOauthUserOtherInfoApiVO> adminOauthUserOtherInfoApiVOS = adminOauthUserOtherInfoApi.getOpenIdByCondition(
                    new AdminOauthUserOtherInfoApiDTO().setUserIds(new ArrayList<>(factoryLeaderUserIdMap.values()))
                            .setSocialType(SocialTypeEnum.WECHAT_MP.getType())).getCheckedData();
            Map<Long, String> leaderOpenIdMap = adminOauthUserOtherInfoApiVOS.stream().collect(Collectors.toMap(AdminOauthUserOtherInfoApiVO::getUserId, AdminOauthUserOtherInfoApiVO::getOpenId));
            for (StaffDO staffDO : staffList) {
                Long factoryId = staffDO.getFactoryId();
                Long leaderUserId = factoryLeaderUserIdMap.get(factoryId);
                String leaderOpenId = leaderOpenIdMap.get(leaderUserId);
                if (leaderOpenId == null) {
                    continue;
                }
                LocalDateTime localDateTime = forkliftAnnualInspectionExpiredTimeMap.get(staffDO.getId());
                if (localDateTime == null) {
                    continue;
                }
                String time = localDateTime.format(Constants.REPO_DATE_FORMAT);
                SubscribeMessageReqDTO dto = new WxMpMsgTemplateUtils().forkliftAnnualInspectionExpiredReminder(new StaffCertificateInformationDTO()
                        .setOpenId(leaderOpenId)
                        .setUserName(staffDO.getNickName())
                        .setCertificateName(CERTIFICATE_NAME)
                        .setTime(time)
                        .setRemarks(staffDO.getNickName() + REMARKS)
                        .setMiniProgramState("formal"));
                subscribeMessageSendApi.sendMpMsg(dto);
            }
            // -- 将这些人设为已经提醒
            staffCertificateInformationService.update(new StaffCertificateInformationDO().setReminderFlag(1),
                    new LambdaQueryWrapper<StaffCertificateInformationDO>()
                            .in(StaffCertificateInformationDO::getId, ids));
        }
        // 返回执行成功
        return ReturnT.SUCCESS;
    }
}
