package org.springblade.system.config;

/**
 * @Author：liang.chao
 * @Date：2025/9/15 - 10:43
 */

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class CronExpressionGenerator {

    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

    public static String generateCron(String archivedType, String cycle, String time, String weekOfDay, String monthDay) {
        if (archivedType == null || time == null || time.trim().isEmpty()) {
            return null;
        }

        try {
            if ("2".equals(archivedType)) {
                // ---- 不定期归档：一次性执行 ----
                LocalDateTime parsed = LocalDateTime.parse(time.trim(), DATETIME_FORMATTER);
                // 再设置秒为 0（即使输入带秒，也统一归零）
                LocalDateTime dateTime = parsed.withSecond(0).withNano(0);
                return String.format("%d %d %d %d %d ? %d",
                        dateTime.getSecond(),
                        dateTime.getMinute(),
                        dateTime.getHour(),
                        dateTime.getDayOfMonth(),
                        dateTime.getMonthValue(),
                        dateTime.getYear()
                );
            } else if ("1".equals(archivedType)) {
                // ---- 定期归档：周期性执行 ----
                if (cycle == null) return null;

                LocalTime parsed = LocalTime.parse(time.trim(), TIME_FORMATTER);
                // 再设置秒为 0（即使输入带秒，也统一归零）
                LocalTime localTime = parsed.withSecond(0).withNano(0);
                int second = localTime.getSecond();
                int minute = localTime.getMinute();
                int hour = localTime.getHour();

                switch (cycle) {
                    // 每天
                    case "daily":
                        return String.format("%d %d %d * * ?", second, minute, hour);
                    // 每周
                    case "weekly":
                        if (weekOfDay == null || weekOfDay.trim().isEmpty()) return null;
                        List<String> days = Arrays.stream(weekOfDay.split(","))
                                .map(String::trim)
                                .filter(d -> !d.isEmpty())
                                .map(CronExpressionGenerator::convertWeekDay)
                                .collect(Collectors.toList());
                        String joinedDays = joinList(days, ",");
                        return joinedDays.isEmpty() ? null :
                                String.format("%d %d %d ? * %s", second, minute, hour, joinedDays);
                    // 每月
                    case "monthly":
                        if (monthDay == null || monthDay.trim().isEmpty()) return null;
                        List<String> validDays = Arrays.stream(monthDay.split(","))
                                .map(String::trim)
                                .filter(d -> !d.isEmpty())
                                .filter(CronExpressionGenerator::isValidDayOfMonth)
                                .collect(Collectors.toList());
                        String validDayStr = joinList(validDays, ",");
                        return validDayStr.isEmpty() ? null :
                                String.format("%d %d %d %s * ?", second, minute, hour, validDayStr);

                    default:
                        return null;
                }
            } else {
                return null;
            }
        } catch (DateTimeParseException e) {
            return null; // 格式错误
        }
    }

    private static String convertWeekDay(String dayStr) {
        if ("1".equals(dayStr)) return "MON";
        if ("2".equals(dayStr)) return "TUE";
        if ("3".equals(dayStr)) return "WED";
        if ("4".equals(dayStr)) return "THU";
        if ("5".equals(dayStr)) return "FRI";
        if ("6".equals(dayStr)) return "SAT";
        if ("7".equals(dayStr)) return "SUN";
        return "";
    }

    private static boolean isValidDayOfMonth(String dayStr) {
        try {
            int day = Integer.parseInt(dayStr);
            return day >= 1 && day <= 31;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    private static String joinList(List<String> list, String delimiter) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
            if (i < list.size() - 1) {
                sb.append(delimiter);
            }
        }
        return sb.toString();
    }

    // --- 测试 ---
    public static void main(String[] args) {
        // 定期归档：精确到秒
        System.out.println("【定期归档】");
        System.out.println(generateCron("1", "daily", "02:30", null, null));
        // 输出：15 30 2 * * ?

        System.out.println(generateCron("1", "weekly", "03:45", "1,5", null));
        // 输出：30 45 3 ? * MON,FRI

        System.out.println(generateCron("1", "monthly", "01:15", null, "1,15"));
        // 输出：0 15 1 1,15 * ?

        // 不定期归档
        System.out.println("【不定期归档】");
        System.out.println(generateCron("2", null, "2025-09-15 10:30", null, null));
        // 输出：45 30 10 15 9 ? 2025
    }
}
