package com.aps.common.util;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * 作者：佟礼
 * 时间：2025-12-11
 */
public class DateGroupUtil {
    /**
     * 通用方法：为List中的对象按指定日期字段（dueDate）的5天跨度分组，生成groupDueDate字段的值
     * @param list 待处理的对象列表
     * @param DateFieldName 日期字段名（如"dueDate"）
     * @param groupDateFieldName 分组日期字段名（如"groupDueDate"）
     * @param <T> 泛型对象类型
     * @throws Exception 反射/日期处理异常
     */
    public static <T> void calculateGroupDueDate(
            List<T> list,
            String DateFieldName,
            String groupDateFieldName,Integer dateDiff
    ) throws Exception {
        if (list == null || list.isEmpty()) {
            return;
        }

        // 1. 反射获取日期字段的Getter/Setter
        Class<?> clazz = list.get(0).getClass();
        Field dueDateField = clazz.getDeclaredField(DateFieldName);
        Field groupDueDateField = clazz.getDeclaredField(groupDateFieldName);
        dueDateField.setAccessible(true);
        groupDueDateField.setAccessible(true);

        // 2. 按dueDate排序（必须先排序，否则分组逻辑失效）
        List<T> sortedList = new ArrayList<>(list);
        sortedList.sort(Comparator.comparing(obj -> {
            try {
                return (LocalDateTime) dueDateField.get(obj);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }));

        // 3. 分组逻辑：以第一个元素的dueDate为初始分组，后续每超过5天则更新分组日期
        LocalDateTime currentGroupDate = (LocalDateTime) dueDateField.get(sortedList.get(0));
        for (T obj : sortedList) {
            LocalDateTime dueDate = (LocalDateTime) dueDateField.get(obj);
            // 计算当前dueDate与当前分组日期的天数差
            long daysDiff = ChronoUnit.DAYS.between(currentGroupDate, dueDate);
            // 若超过5天，则将当前dueDate设为新的分组日期
            if (daysDiff > dateDiff) {
                currentGroupDate = dueDate;
            }
            // 设置groupDueDate
            groupDueDateField.set(obj, currentGroupDate);
        }

        // 4. 将处理后的值写回原列表（保持原列表顺序，因为sortedList是副本）
        for (T obj : list) {
            LocalDateTime dueDate = (LocalDateTime) dueDateField.get(obj);
            // 从sortedList中找到对应dueDate的对象，获取其groupDueDate
            for (T sortedObj : sortedList) {
                if (Objects.equals(dueDateField.get(sortedObj), dueDate)) {
                    groupDueDateField.set(obj, groupDueDateField.get(sortedObj));
                    break;
                }
            }
        }
    }
}
