package com.erp.task.util;

import com.erp.task.exception.TaskException;
import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinition;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Optional;

/**
 * Cron表达式工具类
 */
public class CronUtils {

    private static final CronParser QUARTZ_PARSER = new CronParser(
            CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));

    private static final CronParser UNIX_PARSER = new CronParser(
            CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX));

    /**
     * 验证Cron表达式（Quartz格式）
     */
    public static boolean isValidQuartzCron(String cronExpression) {
        try {
            QUARTZ_PARSER.parse(cronExpression);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 验证Cron表达式（Unix格式）
     */
    public static boolean isValidUnixCron(String cronExpression) {
        try {
            UNIX_PARSER.parse(cronExpression);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 验证并解析Cron表达式
     */
    public static Cron parseQuartzCron(String cronExpression) {
        try {
            return QUARTZ_PARSER.parse(cronExpression);
        } catch (Exception e) {
            throw TaskException.invalidCron(cronExpression);
        }
    }

    /**
     * 获取下次执行时间
     */
    public static Optional<LocalDateTime> getNextFireTime(String cronExpression) {
        return getNextFireTime(cronExpression, LocalDateTime.now());
    }

    /**
     * 获取下次执行时间
     */
    public static Optional<LocalDateTime> getNextFireTime(String cronExpression, LocalDateTime from) {
        try {
            Cron cron = QUARTZ_PARSER.parse(cronExpression);
            ExecutionTime executionTime = ExecutionTime.forCron(cron);
            ZonedDateTime zonedFrom = from.atZone(ZoneId.systemDefault());
            return executionTime.nextExecution(zonedFrom)
                    .map(zdt -> zdt.toLocalDateTime());
        } catch (Exception e) {
            throw TaskException.invalidCron(cronExpression);
        }
    }

    /**
     * 获取指定时间后的第N次执行时间
     */
    public static Optional<LocalDateTime> getNthFireTime(String cronExpression, LocalDateTime from, int n) {
        Optional<LocalDateTime> next = getNextFireTime(cronExpression, from);
        for (int i = 1; i < n && next.isPresent(); i++) {
            next = getNextFireTime(cronExpression, next.get());
        }
        return next;
    }

    /**
     * 获取最近N次执行时间
     */
    public static java.util.List<LocalDateTime> getNextFireTimes(String cronExpression, int n) {
        java.util.List<LocalDateTime> times = new java.util.ArrayList<>();
        Optional<LocalDateTime> next = getNextFireTime(cronExpression);
        for (int i = 0; i < n && next.isPresent(); i++) {
            times.add(next.get());
            next = getNextFireTime(cronExpression, next.get());
        }
        return times;
    }

    /**
     * 获取Cron表达式描述
     */
    public static String getDescription(String cronExpression) {
        try {
            Cron cron = QUARTZ_PARSER.parse(cronExpression);
            return cron.asString();
        } catch (Exception e) {
            return "无效表达式";
        }
    }
}
