package cn.iocoder.yudao.module.system.job.birthday;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.enums.SocialTypeEnum;
import cn.iocoder.yudao.framework.common.template.WxMaMsgTemplateUtils;
import cn.iocoder.yudao.framework.common.template.dto.MessageUnreadReminderDTO;
import cn.iocoder.yudao.framework.common.template.vo.SubscribeMessageReqDTO;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.api.subscribe.SubscribeMessageSendApi;
import cn.iocoder.yudao.module.system.dal.dataobject.auth.AdminOauthUserOtherInfoDO;
import cn.iocoder.yudao.module.system.dal.dataobject.laborcontract.LaborContractDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.auth.AdminOauthUserOtherInfoService;
import cn.iocoder.yudao.module.system.service.auth.dto.AdminOauthUserOtherInfoDTO;
import cn.iocoder.yudao.module.system.service.laborcontract.LaborContractService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobContext;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;

@Component
@Slf4j
@EnableScheduling
public class BirthdayJob {

    @Resource
    private AdminUserMapper adminUserMapper;

    @Resource
    private AdminUserService userService;
    @Resource
    private AdminOauthUserOtherInfoService adminOauthUserOtherInfoService;

    @Resource
    private PermissionService permissionService;

    @Resource
    private SubscribeMessageSendApi subscribeMessageSendApi;

    @Resource
    private LaborContractService laborContractService;


    @XxlJob("birthdayJob")
    @TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
    public ReturnT<String> execute() {

        //获取参数
        XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
        String jobParam = xxlJobContext.getJobParam();
        if (!StringUtil.isNullOrEmpty(jobParam)) {
            // 解析参数
            JSONObject object = new JSONObject(jobParam);
            // 获取角色id
            Long roleId = object.getLong("roleId");
            // 获取提醒时长
            Integer remindDuration = object.getInt("remindDuration");

            Set<Long> userIds = permissionService.getUserRoleIdListByRoleId(CollectionUtils.singleton(roleId));
            //获得用户组中 用户信息
            List<AdminOauthUserOtherInfoDO> list = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(userIds)) {
                list = adminOauthUserOtherInfoService.getOpenIdByCondition(new AdminOauthUserOtherInfoDTO()
                        .setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType())
                        .setUserIds(new ArrayList<>(userIds)));
            }
            // 生日提醒
            birthdayRemind(list);
            // 转正提醒
            PositiveReminders(remindDuration);
            // 合同到期提醒
            ContractReminders(list);
        }
        // 返回执行成功
        return ReturnT.SUCCESS;
    }

    /**
     * 合同到期提醒
     */
    private void ContractReminders(List<AdminOauthUserOtherInfoDO> list) {
        LocalDate now = LocalDate.now();
        List<LaborContractDO> laborContractDOS = laborContractService.getListByEndTime(now);
        if (CollectionUtil.isNotEmpty(laborContractDOS)) {
            // 修改合同状态为过期
            laborContractService.updateLaborContractList(convertList(laborContractDOS, LaborContractDO::getId), LaborContractDO.STATUS_EXPIRE);
            for (AdminOauthUserOtherInfoDO otherInfoDO : list) {
                if (otherInfoDO.getOpenId() != null && !otherInfoDO.getOpenId().isEmpty()) {
                    SubscribeMessageReqDTO dto = new WxMaMsgTemplateUtils().convertMessageUnreadReminder(new MessageUnreadReminderDTO()
                            .setOpenId(otherInfoDO.getOpenId())
                            .setMsgType("合同提醒")
                            .setSender("系统")
                            .setComment("有人合同已过期，请前往PC端查看！")
                            .setSendingTime(DateUtils.dateFormat(new Date(), DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND))
                            .setMiniProgramState("formal"));
                    subscribeMessageSendApi.sendMaMsg(dto);
                }
            }
        }
    }

    /**
     * 转正提醒
     */
    private void PositiveReminders(Integer remindDuration) {
        // 获得提醒日期
        LocalDate remindDate = LocalDate.now().plusDays(remindDuration == null ? 7 : remindDuration);
        // 查询所有试用人员
        // 查询提醒日期内的试用人员合同
        List<LaborContractDO> laborContractDOS = laborContractService.getListByRemindDate(remindDate);
        // 获取需要提醒的用户
        List<AdminUserDO> positiveUserList = userService.getUserList(convertList(laborContractDOS, LaborContractDO::getUserId));
        if (CollUtil.isNotEmpty(positiveUserList)) {
            List<Long> noticeUserIds = positiveUserList.stream().map(AdminUserDO::getId).collect(Collectors.toList());
            List<AdminOauthUserOtherInfoDO> list = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(noticeUserIds)) {
                list = adminOauthUserOtherInfoService.getOpenIdByCondition(new AdminOauthUserOtherInfoDTO()
                        .setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType())
                        .setUserIds(noticeUserIds));
            }
            for (AdminOauthUserOtherInfoDO otherInfoDO : list) {
                if (StrUtil.isNotEmpty(otherInfoDO.getOpenId())) {
                    SubscribeMessageReqDTO dto = new WxMaMsgTemplateUtils().convertMessageUnreadReminder(new MessageUnreadReminderDTO()
                            .setOpenId(otherInfoDO.getOpenId())
                            .setMsgType("转正提醒")
                            .setSender("系统")
                            .setComment("恭喜快要转正了哦，记得走转正流程！")
                            .setSendingTime(DateUtils.dateFormat(new Date(), DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND))
                            .setMiniProgramState("formal"));
                    subscribeMessageSendApi.sendMaMsg(dto);
                }
            }
        }
        log.info("转正提醒，人员为{}", convertList(positiveUserList, AdminUserDO::getNickname));
    }

    /**
     * 生日提醒
     */
    private void birthdayRemind(List<AdminOauthUserOtherInfoDO> userDOs) {
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd"));
        // -- 获取当天月日 生日的人员列表
        List<AdminUserDO> list = adminUserMapper.selectList(new LambdaQueryWrapper<AdminUserDO>()
                .like(AdminUserDO::getBirthdayDay, time));
        if (!list.isEmpty()) {
            for (AdminOauthUserOtherInfoDO otherInfoDO : userDOs) {
                if (otherInfoDO.getOpenId() != null && !otherInfoDO.getOpenId().isEmpty()) {
                    SubscribeMessageReqDTO dto = new WxMaMsgTemplateUtils().convertMessageUnreadReminder(new MessageUnreadReminderDTO()
                            .setOpenId(otherInfoDO.getOpenId())
                            .setMsgType("生日提醒")
                            .setSender("系统")
                            .setComment("今天有人过生日，请前往PC端查看！")
                            .setSendingTime(DateUtils.dateFormat(new Date(), DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND))
                            .setMiniProgramState("formal"));
                    subscribeMessageSendApi.sendMaMsg(dto);
                }
            }
            log.info("生日提醒，生日为{}，人员为{}", time, convertList(list, AdminUserDO::getNickname));
        }
    }
}
