package cn.iocoder.yudao.module.property.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.common.BaseConstants;
import cn.iocoder.yudao.common.DictBaseConstants;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.company.vo.CompanyRespVO;
import cn.iocoder.yudao.module.property.entity.Property;
import cn.iocoder.yudao.module.property.mapper.PropertyMapper;
import cn.iocoder.yudao.module.property.service.PropertyService;
import cn.iocoder.yudao.module.property.vo.PropertyReqVO;
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.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 企业管理-资产管理 接口实现类
 *
 * @author 小李
 * @date 16:41 2024/8/15
 **/
@Service
public class PropertyServiceImpl extends ServiceImpl<PropertyMapper, Property> implements PropertyService {

    @Resource
    private AdminUserApi userApi;

    @Resource
    private DeptApi deptApi;

    @Resource
    private DictDataApi dataApi;

    @Resource
    private NotifyMessageSendApi sendApi;

    /**
     * 企业管理-资产分页
     *
     * @param pageReqVO 查询对象
     * @author 小李
     * @date 16:15 2024/8/15
     **/
    @Override
    public IPage<Property> getPropertyPage(PropertyReqVO pageReqVO, Page<Property> page) {
        return baseMapper.getPropertyPage(pageReqVO, page);
    }

    /**
     * 创建资产
     *
     * @param createReqVO
     * @author 小李
     * @date 18:26 2024/8/15
     **/
    @Override
    @DSTransactional
    public void createProperty(PropertyReqVO createReqVO) {
        // 获取当前登录用户部门ID和企业ID
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        AdminUserRespDTO user = userApi.getUser(userId);
        createReqVO.setDeptId(user.getDeptId());
        DeptRespDTO dept = deptApi.getDept(user.getDeptId());
        createReqVO.setCorpId(dept.getCorpId());

        // 创建资产
        baseMapper.insert(createReqVO);
    }

    /**
     * 获得资产记录
     *
     * @param id 资产ID
     * @author 小李
     * @date 18:45 2024/8/15
     **/
    @Override
    public Property getProperty(String id) {
        return baseMapper.selectById(id);
    }

    /**
     * 更新资产
     *
     * @param updateReqVO 资产对象
     * @author 小李
     * @date 18:57 2024/8/15
     **/
    @Override
    public void updateProperty(PropertyReqVO updateReqVO) {
        baseMapper.updateById(updateReqVO);
    }

    /**
     * 删除资产
     *
     * @param id 资产ID
     * @author 小李
     * @date 19:20 2024/8/15
     **/
    public void deleteProperty(String id) {
        baseMapper.deleteById(id);
    }

    /**
     * 检测是否有临期、过期资产，有就通知
     *
     * @param adminUsers
     * @author 小李
     * @date 8:47 2024/8/16
     **/
    @Override
    public void noticePropertyExpired(List<CompanyRespVO> adminUsers) {
        // 构建分页
        LambdaQueryWrapper<Property> queryWrapper = new LambdaQueryWrapper<>();
        Page<Property> page = new Page<>(1, BaseConstants.BATCH_SIZE);
        // 获取临期判定时间
        List<DictDataRespDTO> dictDataList = dataApi.getDictDataList(DictBaseConstants.COMPANY_PROPERTY_EXPIRED);
        Long ruleDay = null;
        if (ObjectUtil.isNotEmpty(dictDataList)) {
            ruleDay = Long.valueOf(dictDataList.get(0).getValue());
        }
        while (ObjectUtil.isNotEmpty(ruleDay)) {
            // 查询一页数据
            Page<Property> propertyPage = baseMapper.selectPage(page, queryWrapper);
            // 分类临期和过期
            // 这里重新赋值是因为不重新赋值用不了，我也不知道为什么，看到这里的人知道的话可以给我讲讲
            Long finalRuleDay = ruleDay;
            propertyPage.getRecords().forEach(item -> {
                LocalDate currentDate = LocalDate.now();
                LocalDate nextKeepDate = item.getNextKeepDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                // 计算离当前时间还有多少天
                Long day = ChronoUnit.DAYS.between(currentDate, nextKeepDate);
                // 拿到当前记录的管理员ID
                List<CompanyRespVO> collect = adminUsers.stream().filter(company -> company.getId() == item.getCorpId()).collect(Collectors.toList());
                if (ObjectUtil.isNotEmpty(collect)) {
                    Long userId = collect.get(0).getUserDTO().getId();
                    // day 小于0是过期了 小于等于finalRuleDay是临期了 其他就正常的
                    if (day < 0) {
                        // 通知管理员
                        sendMessage(item, BaseConstants.PROPERTY_EXPIRED, userId, day);
                        // 通知使用人
                        sendMessage(item, BaseConstants.PROPERTY_EXPIRED, Long.valueOf(item.getUserId()), day);
                    } else if (day <= finalRuleDay) {
                        // 通知管理员
                        sendMessage(item, BaseConstants.PROPERTY_INTERIM_PERIOD, userId, day);
                        // 通知使用人
                        sendMessage(item, BaseConstants.PROPERTY_INTERIM_PERIOD, Long.valueOf(item.getUserId()), day);
                    }
                }

            });

            // 没有下一页了就退出
            if (!propertyPage.hasNext()) {
                break;
            }

            // 翻页
            page.setCurrent(page.getCurrent() + 1);
        }
    }

    /**
     * 发送通知
     *
     * @param property     发送的资产信息
     * @param templateCode 使用的模板
     * @param noticeId     通知到的人
     * @param day          天数
     * @author 小李
     * @date 9:29 2024/8/16
     **/
    private void sendMessage(Property property, String templateCode, Long noticeId, Long day) {
        // 准备发送参数
        Map<String, Object> templateParams = new HashMap<>();
        // 什么资产
        templateParams.put("propertyName", property.getPropName());
        // 还有多少天过期或已过期多少天，可能是负数，绝对值一下
        templateParams.put("day", Math.abs(day));

        // 发送
        sendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO()
                .setUserId(noticeId)
                .setTemplateCode(templateCode).setTemplateParams(templateParams));
    }
}