package com.nokia.tsl_data.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.nokia.tsl_data.dao.TaskRecordRepository;
import com.nokia.tsl_data.dao.TslDataDao;
import com.nokia.tsl_data.entity.TaskRecord;
import com.nokia.tsl_data.properties.TslDataProperties;
import com.nokia.tsl_data.scheduling.entity.RunnableTask;
import com.nokia.tsl_data.scheduling.service.TaskScheduleService;
import com.nokia.tsl_data.util.DateFormatUtil;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 定时任务
 */
@Slf4j
@Service
public class TaskService {

    @Autowired
    private TslDataDao tslDataDao;
    @Autowired
    private TaskRecordRepository taskRecordRepository;
    @Autowired
    private WorkFlowService workFlowService;
    @Autowired
    private DataWarehouseService dataWarehouseService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private HighQualityDataService highQualityDataService;
    @Autowired
    private TaskScheduleService taskScheduleService;
    @Autowired
    private ReportServiceV3 reportServiceV3;
    @Autowired
    private TslDataProperties tslDataProperties;
    @Autowired
    private ManagementDetailService managementDetailService;

    /**
     * 每日定时任务 每天中午1点半执行入库任务
     */
    @Scheduled(cron = "0 30 13 * * *")
    public void dailyWarehouseTask() {
        // 这里的时间要向前一天
        String day = DateFormatUtil.ofPattern("yyyyMMdd").format(Instant.now().plus(-1L, ChronoUnit.DAYS));
        // 调度一次 taskService.wareHouseTask(day)
        RunnableTask task = new RunnableTask()
                .setTaskId("warehouse_cron_" + day)
                .setBeanName("taskService")
                .setMethodName("warehouseTask")
                .setMethodParameter(day);
        taskScheduleService.schedule(task);
    }

    /**
     * 指定日期任务
     */
    public void warehouseTask(String day) {
        // 检查源是否具备
        String result = dataWarehouseService.checkSource(day);
        if (StringUtils.hasLength(result)) {
            // 存在异常情况，发送运维消息
            messageService.error(result);
            // 延时调度，间隔一段时间后再次调度
            taskScheduleService.schedule(new RunnableTask()
                    .setTaskId("warehouse_rescedule_" + day + "_" + System.currentTimeMillis())
                    .setBeanName("taskService")
                    .setMethodName("warehouseTask")
                    .setMethodParameter(day)
                    .setDelay(3600L));
        } else {
            try {
                // 执行入库任务
                dataWarehouseService.warehouse(day);
                // 生成HighQualityData
                highQualityDataService.generateHighQualityData(day);
                // 生成ManagementDetail
                managementDetailService.generateForDay(day);
                // 报表+截图
                generateReportV3(day);
            } catch (Exception e) {
                messageService.error("指定日期任务失败：" + e.getMessage());
                e.printStackTrace();
                throw new RuntimeException("指定日期任务失败：" + e.getMessage());
            }
        }
    }

    /**
     * 生成第三版报表
     */
    public void generateReportV3(String day) {
        // 1. 检查文件路径
        String fileName = tslDataProperties.getOutputFileNamePrefix() + day + ".xlsx";
        File file = Paths.get(tslDataProperties.getOutputPath(), "V3", day).toFile();
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            System.out.println(mkdirs);
        }
        file = Paths.get(file.getAbsolutePath(), fileName).toFile();
        // 2. 生成报表
        reportServiceV3.generateReport(file, day);
        // 3. 截图
        reportServiceV3.screenShot(file, day);
        // 4. 总结
        reportServiceV3.messageToSend(file, day);
    }

    /**
     * 从工单系统定时更新数据
     * 调度周期每三小时的10分调度一次
     */
    @Scheduled(cron = "0 10 0/3 * * *")
    public void updateWorkFlowBasicDataTask() {
        log.info("从工单系统定时更新数据 任务开始...");
        Instant start = taskRecordRepository.findLastSuccessUpdateWorkFlowBasicDataTaskEndInstant();
        Instant end = Instant.now();
        TaskRecord taskRecord = workFlowService.updateWorkFlowBasicData(start, end);
        taskRecordRepository.save(taskRecord);
        log.info("从工单系统定时更新数据 任务完成...");
    }

    /**
     * 定时删除过期的临时表
     * 调度周期，每天凌晨1点调度一次
     */
    @Scheduled(cron = "0 0 1 * * *")
    public void tempTableCleanCronTask() {
        log.info("定时删除过期的临时表 任务开始...");
        TaskRecord taskRecord = new TaskRecord();
        taskRecord.setTaskName("临时表清理");
        taskRecord.setStartTime(Instant.now());
        List<String> tempTableNames = tslDataDao.selectTempTableNames();
        long zeroClockToday = DateFormatUtil.zeroClockTodayLong();
        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        taskRecord.setTaskInfo(jsonObject);
        for (String tempTableName : tempTableNames) {
            // 保留当天的临时表不删除
            long createTimestamp = Long.parseLong(tempTableName.substring(tempTableName.indexOf("_temp_") + 6));
            if (createTimestamp < zeroClockToday) {
                tslDataDao.dropTempTable(tempTableName);
                jsonArray.add(tempTableName);
            }
        }
        if (!jsonArray.isEmpty()) {
            jsonObject.put("tempTableNames", jsonArray);
        }
        taskRecord.setEndStatus(0);
        taskRecord.setEndTime(Instant.now());
        taskRecord.setTimeCost(taskRecord.getEndTime().toEpochMilli() - taskRecord.getStartTime().toEpochMilli());
        taskRecordRepository.save(taskRecord);
        log.info("定时删除过期的临时表 任务完成...");
    }
}
