package com.njzscloud.common.sichen.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.sichen.contant.ScheduleType;
import com.njzscloud.common.sichen.pojo.param.SearchTaskParam;
import com.njzscloud.common.sichen.pojo.param.SearchTaskResult;
import com.njzscloud.common.sichen.support.TaskInfo;
import com.njzscloud.common.sichen.support.TaskStore;
import com.njzscloud.common.sichen.util.TaskUtil;

import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class MemoryTaskStoreService implements TaskStore {
    List<TaskInfo> TASKS = new LinkedList<>();

    @Override
    public void registerTask(TaskInfo taskInfo) {
        ScheduleType scheduleType = taskInfo.getScheduleType();
        long criticalTiming = TaskUtil.computedNextTiming(scheduleType, taskInfo.getScheduleConf());
        boolean disabled = scheduleType != ScheduleType.Manually && (criticalTiming <= 0 || taskInfo.isDisabled());
        TASKS.add(new TaskInfo(taskInfo)
            .setCriticalTiming(criticalTiming)
            .setDisabled(disabled)
            .setBuiltin(true)
        );
    }

    @Override
    public List<TaskInfo> loadTask(long soon) {
        return TASKS.stream()
            .filter(it -> {
                long criticalTiming = it.getCriticalTiming();
                ScheduleType scheduleType = it.getScheduleType();
                boolean disabled = it.isDisabled();
                return !disabled && (criticalTiming > 0 && criticalTiming <= soon) && scheduleType != ScheduleType.Manually;
            }).map(TaskInfo::new).collect(Collectors.toList());
    }


    @Override
    public void updateCriticalTiming(long id, long criticalTiming) {
        TASKS.stream().filter(it -> it.getId() == id)
            .findFirst()
            .ifPresent(it -> it.setCriticalTiming(criticalTiming)
                .setDisabled(criticalTiming <= 0));
    }

    @Override
    public boolean trigger(Long id) {
        Optional<TaskInfo> optional = TASKS.stream().filter(it -> it.getId() == id).findFirst();
        if (optional.isPresent()) {
            TaskUtil.execute(optional.get(), true);
            return true;
        } else {
            return false;
        }
    }

    public PageResult<SearchTaskResult> paging(PageParam pageParam, SearchTaskParam searchTaskParam) {

        String taskName = searchTaskParam.getTaskName();
        String fn = searchTaskParam.getFn();
        ScheduleType scheduleType = searchTaskParam.getScheduleType();

        return PageResult.of(pageParam,
            TASKS.stream()
                .filter(it -> {
                    boolean f = true;
                    if (StrUtil.isNotBlank(taskName)) {
                        f = it.getTaskName().contains(taskName);
                    }
                    if (StrUtil.isNotBlank(fn)) {
                        f = f && it.getFn().contains(fn);
                    }
                    if (scheduleType != null) {
                        f = f && (scheduleType == it.getScheduleType());
                    }
                    return f;
                })
                .map(it -> BeanUtil.copyProperties(it, SearchTaskResult.class)
                    .setBuiltin(Boolean.TRUE)
                ).toList()
        );
    }

    public SearchTaskResult detail(Long id) {
        Optional<TaskInfo> optional = TASKS.stream().filter(it -> it.getId() == id).findFirst();
        return optional.map(it -> BeanUtil.copyProperties(it, SearchTaskResult.class)
            .setBuiltin(Boolean.TRUE)).orElse(null);
    }
}
