package com.xunmei.core.retrieval.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xunmei.common.core.constant.ErrorMsgConstants;
import com.xunmei.common.core.constant.SecurityConstants;
import com.xunmei.common.core.domain.DateRange;
import com.xunmei.common.core.domain.R;
import com.xunmei.common.core.enums.RetrievalTaskCycle;
import com.xunmei.common.core.utils.DateHelper;
import com.xunmei.common.core.utils.DateUtils;
import com.xunmei.common.core.utils.IDHelper;
import com.xunmei.common.core.utils.Ymd;
import com.xunmei.common.core.web.page.TableDataInfo;
import com.xunmei.core.access.domain.TMonitoringRetrievalPlan;
import com.xunmei.core.access.dto.CoreMonitoringTaskRegistrationDTO;
import com.xunmei.common.core.domain.retrieval.domain.CoreMonitoringRetrievalTask;
import com.xunmei.common.core.domain.retrieval.dto.RetrievalTaskPageDto;
import com.xunmei.core.access.service.ITMonitoringRetrievalPlanService;
import com.xunmei.core.retrieval.mapper.CoreMonitoringRetrievalTaskMapper;
import com.xunmei.core.retrieval.service.ICoreMonitoringRetrievalTaskService;
import com.xunmei.common.core.domain.retrieval.vo.CoreMonitoringRetrievalTaskVo;
import com.xunmei.system.api.RemoteDictDataService;
import com.xunmei.system.api.RemoteOrgService;
import com.xunmei.system.api.domain.SysDictData;
import com.xunmei.system.api.domain.SysOrg;
import com.xunmei.system.api.function.RemoteCallHandlerExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 监控调阅任务Service业务层处理
 *
 * @author xunmei
 * @date 2023-08-25
 */
@Service
public class CoreMonitoringRetrievalTaskServiceImpl extends ServiceImpl<CoreMonitoringRetrievalTaskMapper, CoreMonitoringRetrievalTask> implements ICoreMonitoringRetrievalTaskService {
    @Resource
    private CoreMonitoringRetrievalTaskMapper coreMonitoringRetrievalTaskMapper;
    @Resource
    private RemoteOrgService orgService;
    @Resource
    private RemoteDictDataService dictDataService;
    @Resource
    private ITMonitoringRetrievalPlanService tMonitoringRetrievalPlanService;

    @Override
    public TableDataInfo selectPage(RetrievalTaskPageDto request) {

        Page<CoreMonitoringRetrievalTaskVo> page;
        //分页
        if (request.getPageNum() != null && request.getPageSize() != null) {
            page = new Page<>(request.getPageNum(), request.getPageSize());
        } else {
            page = new Page<>();
        }
        //下穿
        if (request.getCheckSub()) {
            SysOrg sysOrg = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.selectTopOrg(SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
            request.setOrgPath(sysOrg.getPath());
            request.setOrgId(null);
        }
        //获取数据
        page = coreMonitoringRetrievalTaskMapper.selectPageList(page, request);
        //抓换为TableDataInfo适配前端
        return TableDataInfo.build(page);
    }

    @Override
    public void export(RetrievalTaskPageDto request, HttpServletResponse response) throws IOException {
        //不分页
        request.setPageSize(null);
        request.setPageNum(null);
        SysOrg sysOrg = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.selectTopOrg(SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
        List<SysDictData> listDict = RemoteCallHandlerExecutor.executeRemoteCall(() -> dictDataService.dictType("retrieval_task_status", SecurityConstants.INNER), ErrorMsgConstants.QUERY_DICT_DATA_ERROR);
        final TableDataInfo tableDataInfo = this.selectPage(request);
        if (ObjectUtil.isEmpty(tableDataInfo.getRows())) {
            throw new RuntimeException("导出数据为空!");
        }
        List<CoreMonitoringRetrievalTaskVo> list = this.selectPage(request).getRows();
        list.forEach(r -> {
            r.setStatusText(listDict.stream().filter(d -> d.getDictValue().equals(r.getStatus())).findFirst().orElse(new SysDictData()).getDictLabel());
        });
        list.forEach(r -> r.setNo(list.indexOf(r) + 1));
        ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.addHeaderAlias("序号", "no");
        writer.addHeaderAlias("任务名称", "taskName");
        writer.addHeaderAlias("开始时间", "planStartTime");
        writer.addHeaderAlias("结束时间", "planEndTime");
        writer.addHeaderAlias("状态", "statusText");
        writer.addHeaderAlias("调阅机构", "orgName");
        writer.addHeaderAlias("调阅角色", "roleName");
        writer.addHeaderAlias("调阅开始时间", "startTime");
        writer.addHeaderAlias("调阅结束时间", "endTime");
        writer.addHeaderAlias("调阅人", "retrievalUserName");
        writer.addHeaderAlias("异常数", "exceptionCount");
        //只保留别名的数据
        writer.setOnlyAlias(true);
        // 默认配置
        writer.write(list, true);
        // 设置content—type
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset:utf-8");
        // 设置标题
        String fileName = URLEncoder.encode("【" + sysOrg.getName() + "】-监控调阅任务记录" + DateHelper.getDateString(new Date()), "UTF-8");
        //Content-disposition是MIME协议的扩展，MIME协议指示MIME用户代理如何显示附加的文件。
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".et");
        ServletOutputStream outputStream = response.getOutputStream();
        //将Writer刷新到OutPut
        writer.flush(outputStream, true);
        outputStream.close();
        writer.close();
    }

    @Override
    public List<CoreMonitoringRetrievalTask> selectListApp(CoreMonitoringTaskRegistrationDTO coreMonitoringTaskRegistrationDTO) {
        return baseMapper.selectListApp(coreMonitoringTaskRegistrationDTO);
    }


    /**
     * 查询监控调阅任务
     *
     * @param id 监控调阅任务主键
     * @return 监控调阅任务
     */
    @Override
    public CoreMonitoringRetrievalTask selectCoreMonitoringRetrievalTaskById(Long id) {
        return coreMonitoringRetrievalTaskMapper.selectById(id);
    }

    /**
     * 查询监控调阅任务列表
     *
     * @param CoreMonitoringRetrievalTask 监控调阅任务
     * @return 监控调阅任务
     */
    @Override
    public List<CoreMonitoringRetrievalTask> selectCoreMonitoringRetrievalTaskList(CoreMonitoringRetrievalTask CoreMonitoringRetrievalTask) {
        return coreMonitoringRetrievalTaskMapper.selectList(new QueryWrapper<>(CoreMonitoringRetrievalTask));
    }

    /**
     * 新增监控调阅任务
     *
     * @param CoreMonitoringRetrievalTask 监控调阅任务
     * @return 结果
     */
    @Override
    public int insertCoreMonitoringRetrievalTask(CoreMonitoringRetrievalTask CoreMonitoringRetrievalTask) {
        return coreMonitoringRetrievalTaskMapper.insert(CoreMonitoringRetrievalTask);
    }

    /**
     * 修改监控调阅任务
     *
     * @param CoreMonitoringRetrievalTask 监控调阅任务
     * @return 结果
     */
    @Override
    public int updateCoreMonitoringRetrievalTask(CoreMonitoringRetrievalTask CoreMonitoringRetrievalTask) {
        return coreMonitoringRetrievalTaskMapper.updateById(CoreMonitoringRetrievalTask);
    }

    /**
     * 批量删除监控调阅任务
     *
     * @param ids 需要删除的监控调阅任务主键
     * @return 结果
     */
    @Override
    public int deleteCoreMonitoringRetrievalTaskByIds(Long[] ids) {
        return coreMonitoringRetrievalTaskMapper.deleteBatchIds(Arrays.asList((ids)));
    }

    /**
     * 删除监控调阅任务信息
     *
     * @param id 监控调阅任务主键
     * @return 结果
     */
    @Override
    public int deleteCoreMonitoringRetrievalTaskById(Long id) {
        return coreMonitoringRetrievalTaskMapper.deleteById(id);
    }

    /**
     * 无周期任务生成
     */
    public void noCycleTask(List<TMonitoringRetrievalPlan> planList){
        List<SysOrg> orgList = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.findAllOrg(SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
        List<CoreMonitoringRetrievalTask> taskList = new ArrayList<>();
        LocalDate taskTime = planList.get(0).getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();;
        for (TMonitoringRetrievalPlan plan : planList) {
            //获取计划关联的机构
            List<SysOrg> listByType = orgList.stream().filter(r->r.getId().equals(plan.getOrgId())&&r.getDeleted()==0&&r.getIsLock()==0).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(listByType)){
                List<CoreMonitoringRetrievalTask> list = this.buildCoreMonitoringRetrievalTask(plan, taskTime,listByType.get(0));
                if (CollectionUtil.isNotEmpty(list)) {
                    taskList.addAll(list);
                }
            }
        }
        this.saveBatch(taskList);
    }
    /**
     * 每天生成日任务 如果当天是周一还需生成周任务
     *
     * @param taskTime
     */
    @Override
    public void dayTask(LocalDate taskTime) {
        if (ObjectUtil.isEmpty(taskTime)) {
            taskTime = LocalDate.now();
        }

        List<CoreMonitoringRetrievalTask> list = new ArrayList<>();
        //获取所有机构
        List<SysOrg> orgList = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.findAllOrg(SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
        if(CollectionUtil.isEmpty(orgList)){
            log.error("获取机构信息失败!");
            return;
        }
        //是周一生成周任务
        if (taskTime.getDayOfWeek() == DayOfWeek.MONDAY) {
            List<CoreMonitoringRetrievalTask> listWeek = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.WEEKCYCLE.getCode(), taskTime,orgList);
            if (CollectionUtil.isNotEmpty(listWeek)) {
                list.addAll(listWeek);
            }
        }
        //生成每日任务
        List<CoreMonitoringRetrievalTask> listDay = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.DAYCYCLE.getCode(), taskTime,orgList);
        if (CollectionUtil.isNotEmpty(listDay)) {
            list.addAll(listDay);
        }
        this.saveBatch(list);

    }

    /**
     * 1.1生成周期为每月，每季，每半年，每年的任务
     * 4.1||10.1日生成周期为每月，每季
     * 7.1日获取执行周期为每月，每季,每半年的
     * 其他日期生成月任务
     *
     * @param taskTime
     */
    @Override
    public void monthTask(LocalDate taskTime) {
        if (ObjectUtil.isEmpty(taskTime)) {
            taskTime = LocalDate.now();
        }
        List<CoreMonitoringRetrievalTask> list = new ArrayList<>();
        //获取所有机构
        List<SysOrg> orgList = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.findAllOrg(SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
        //判断taskTime不是每月1号将taskTime设置为每月1号
        if (taskTime.getDayOfMonth() != 1) {
            taskTime = taskTime.withDayOfMonth(1);
        }
        //1.1生成周期为每月，每季，每半年，每年的任务
        if (taskTime.getMonthValue() == 1) {
            //季度任务
            List<CoreMonitoringRetrievalTask> listQuarter = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.QUARTERCYCLE.getCode(), taskTime, orgList);
            if (CollectionUtil.isNotEmpty(listQuarter)) {
                list.addAll(listQuarter);
            }
            //半年任务
            List<CoreMonitoringRetrievalTask> listHalfYear = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.HALFYEARCYCLE.getCode(), taskTime, orgList);
            if (CollectionUtil.isNotEmpty(listHalfYear)) {
                list.addAll(listHalfYear);
            }
            //年任务
            List<CoreMonitoringRetrievalTask> listYear = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.YEARCYCLE.getCode(), taskTime, orgList);
            if (CollectionUtil.isNotEmpty(listYear)) {
                list.addAll(listYear);
            }
        }
        //4.1||10.1日生成周期为每月，每季
        if (taskTime.getMonthValue() == 4 || taskTime.getMonthValue() == 10) {
            //季度任务
            List<CoreMonitoringRetrievalTask> listQuarter = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.QUARTERCYCLE.getCode(), taskTime, orgList);
            if (CollectionUtil.isNotEmpty(listQuarter)) {
                list.addAll(listQuarter);
            }
        }
        //7.1日获取执行周期为每月，每季,每半年的
        if (taskTime.getMonthValue() == 7) {
            //季度任务
            List<CoreMonitoringRetrievalTask> listQuarter = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.QUARTERCYCLE.getCode(), taskTime, orgList);
            if (CollectionUtil.isNotEmpty(listQuarter)) {
                list.addAll(listQuarter);
            }
            //半年任务
            List<CoreMonitoringRetrievalTask> listHalfYear = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.HALFYEARCYCLE.getCode(), taskTime, orgList);
            if (CollectionUtil.isNotEmpty(listHalfYear)) {
                list.addAll(listHalfYear);
            }
        }
        //所有日期都要生成月任务
        List<CoreMonitoringRetrievalTask> listMonth = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.MONTHCYCLE.getCode(), taskTime, orgList);
        if (CollectionUtil.isNotEmpty(listMonth)) {
            list.addAll(listMonth);
        }
        this.saveBatch(list);

    }

    /**
     *
     * @param cycle 周期
     * @param taskTime 日期
     * @param orgList 机构
     * @return
     */

    private List<CoreMonitoringRetrievalTask> buildCoreMonitoringRetrievalTask(Integer cycle, LocalDate taskTime,List<SysOrg> orgList) {
        List<CoreMonitoringRetrievalTask> taskList = new ArrayList<>();
        //获取计划
        QueryWrapper<TMonitoringRetrievalPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TMonitoringRetrievalPlan::getPlanCycle, cycle);
        queryWrapper.lambda().eq(TMonitoringRetrievalPlan::getPlanStatus, 0);
        queryWrapper.lambda().eq(TMonitoringRetrievalPlan::getIsDeleted, 0);
        queryWrapper.lambda().eq(TMonitoringRetrievalPlan::getCreateType, 1);
        List<TMonitoringRetrievalPlan> planList = tMonitoringRetrievalPlanService.list();
        //按计划生成任务
        for (TMonitoringRetrievalPlan plan : planList) {
            //获取计划关联的机构
            List<SysOrg> listByType = orgList.stream().filter(r->r.getId().equals(plan.getOrgId())&&r.getDeleted()==0&&r.getIsLock()==0).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(listByType)){
                List<CoreMonitoringRetrievalTask> list = this.buildCoreMonitoringRetrievalTask(plan, taskTime,listByType.get(0));
                if (CollectionUtil.isNotEmpty(list)) {
                    taskList.addAll(list);
                }
            }
        }
        return taskList;
    }

    /**
     *
     * @param plan 计划
     * @param taskTime 日期
     * @param sysOrg 机构
     * @return
     */
    private List<CoreMonitoringRetrievalTask> buildCoreMonitoringRetrievalTask(TMonitoringRetrievalPlan plan, LocalDate taskTime,SysOrg sysOrg) {
         List<CoreMonitoringRetrievalTask> taskList = new ArrayList<>();
              Long batchNum = IDHelper.id();
              for(int i=0;i<plan.getPlanFrequency();i++){
                  CoreMonitoringRetrievalTask task = this.buildCoreMonitoringRetrievalTask(batchNum,i+1,plan,sysOrg,taskTime);
                  taskList.add(task);
              }

      return taskList;

    }

    /**
     *
     * @param batchNum 批次
     * @param frequency 第几次
     * @param plan 计划
     * @param sysOrg 机构
     * @param taskTime 日期
     * @return
     */
    private CoreMonitoringRetrievalTask buildCoreMonitoringRetrievalTask(Long batchNum, int frequency, TMonitoringRetrievalPlan plan, SysOrg sysOrg,LocalDate taskTime) {
        Date dateTime = Date.from(taskTime.atStartOfDay(ZoneId.systemDefault()).toInstant());
        Ymd ymd = Ymd.of(dateTime);
        DateRange dateRange =null;
        if(Integer.parseInt(plan.getPlanCycle())==0){
           //无周期任务获取计划时间//重计划中获取
            dateRange.setStartTime(plan.getStartTime());
            dateRange.setEndTime(plan.getEndTime());
        }else {
            //周期任务获取计划时间
            dateRange = DateUtils.getStartAndEnd(dateTime,Integer.parseInt(plan.getPlanCycle()));
        }
        CoreMonitoringRetrievalTask task = new CoreMonitoringRetrievalTask();
        task.setId(IDHelper.id());
        task.setTaskName(plan.getPlanName()+"第"+frequency+"次调阅");
        task.setCycle(Integer.parseInt(plan.getPlanCycle()));
        task.setOrgId(sysOrg.getId());
        task.setOrgPath(sysOrg.getPath());
        task.setOrgName(sysOrg.getName());
        task.setBatchNum(batchNum);
        task.setPlanId(plan.getId());
        task.setOrderNum(frequency);
        task.setPlanEndTime(dateRange.getStartTime());
        task.setPlanEndTime(dateRange.getEndTime());
        task.setYmdDate(ymd.getDate());
        task.setYmdYear(ymd.getYear());
        task.setYmdHalfyear(ymd.getHalfyear());
        task.setYmdQuarter(ymd.getQuarter());
        task.setYmdMonth(ymd.getMonth());
        task.setYmdWeek(ymd.getWeek());
        task.setYmdDay(ymd.getDay());
        task.setRoleId(plan.getRoleId());
        task.setStatus(0);
        return task;
    }

}
