package com.njzscloud.common.sichen.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.sichen.pojo.param.AddTaskParam;
import com.njzscloud.common.sichen.pojo.param.ModifyTaskParam;
import com.njzscloud.common.sichen.pojo.param.SearchTaskParam;
import com.njzscloud.common.sichen.pojo.param.SearchTaskResult;
import com.njzscloud.common.sichen.service.CombineStoreService;
import com.njzscloud.common.sichen.support.CronExpression;
import com.njzscloud.common.sichen.support.TaskInfo;
import com.njzscloud.common.sichen.support.TaskStore;
import com.njzscloud.common.sichen.util.TaskUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 用户定时任务
 */
@Slf4j
@RestController
@RequestMapping("/task")
@RequiredArgsConstructor
public class TaskController {

    private final CombineStoreService taskStore;

    /**
     * 新增
     */
    @PostMapping("/add")
    public R<?> add(@RequestBody @Validated AddTaskParam addTaskParam) {
        taskStore.registerTask(BeanUtil.copyProperties(addTaskParam, TaskInfo.class));
        return R.success();
    }

    /**
     * 修改
     */
    @PostMapping("/modify")
    public R<?> modify(ModifyTaskParam modifyTaskParam) {
        taskStore.dbTaskService.modify(modifyTaskParam);
        return R.success();
    }

    /**
     * 禁用
     */
    @GetMapping("/disable")
    public R<?> disable(
        @RequestParam("id") Long id,
        @RequestParam("disable") Boolean disable
    ) {
        taskStore.dbTaskService.disable(id, disable);
        return R.success();
    }

    /**
     * 删除
     */
    @PostMapping("/del")
    public R<?> del(@RequestBody List<Long> ids) {
        Assert.notEmpty(ids, () -> Exceptions.clierr("未指定要删除的数据"));
        taskStore.dbTaskService.del(ids);
        return R.success();
    }

    /**
     * 处理函数列表
     */
    @GetMapping("/fn")
    public R<List<Map<Object, Object>>> fn(@RequestParam(value = "keywords", required = false) String keywords) {
        return R.success(TaskStore.searchFn(keywords));
    }

    /**
     * 详情
     */
    @GetMapping("/detail")
    public R<SearchTaskResult> detail(@RequestParam("id") Long id) {
        TaskStore.RLOCK.lock();
        try {
            SearchTaskResult searchTaskResult = taskStore.memoryTaskStoreService.detail(id);
            if (searchTaskResult == null) searchTaskResult = taskStore.dbTaskService.detail(id);
            return R.success(searchTaskResult);
        } finally {
            TaskStore.RLOCK.unlock();
        }
    }

    /**
     * 检查并获取最近执行时间
     */
    @GetMapping("/check_expression")
    public R<?> detail(@RequestParam("expression") String expression) {
        CronExpression cronExpression;
        try {
            cronExpression = new CronExpression(expression);
        } catch (ParseException e) {
            return R.failed(ExceptionMsg.CLI_ERR_MSG, "表达式错误：{}", e.getMessage());
        }
        Date timePoint = new Date();
        int i = 0;
        ArrayList<String> list = new ArrayList<>();
        while (i < 10) {
            i++;
            Date nextValidTimeAfter = cronExpression.getNextValidTimeAfter(timePoint);
            String format = DateUtil.format(nextValidTimeAfter, "yyyy-MM-dd HH:mm:ss");
            list.add(format);
            timePoint = nextValidTimeAfter;
        }
        return R.success(list);
    }

    /**
     * 分页查询
     */
    @GetMapping("/paging")
    public R<PageResult<SearchTaskResult>> paging(PageParam pageParam, SearchTaskParam searchTaskParam) {
        TaskStore.RLOCK.lock();
        try {
            if (searchTaskParam.isBuiltin()) {
                return R.success(taskStore.memoryTaskStoreService.paging(pageParam, searchTaskParam));
            } else {
                return R.success(taskStore.dbTaskService.paging(pageParam, searchTaskParam));
            }
        } finally {
            TaskStore.RLOCK.unlock();
        }
    }

    /**
     * 触发一次任务
     */
    @GetMapping("/trigger")
    public R<?> trigger(@RequestParam("id") Long id) {
        return R.success(TaskUtil.trigger(id));
    }
}
