package com.goafanti.common.utils;

import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.error.BusinessException;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

	public static final String	YEAR_SPAN		= "yearSpan";

	public static final String	QUARTER_SPAN	= "quarterSpan";

	public static final String	MONTH_SPAN		= "monthSpan";

	public static final String	WEEK_SPAN		= "weekSpan";

	public static final String	DAY_SPAN		= "daySpan";

	private static String[] parsePatterns = {
			"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
			"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
			"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM",
			"yyyy年MM月dd日", "yyyy年MM月dd日 HH:mm:ss", "yyyy年MM月dd日 HH:mm", "yyyy年MM月",};

	/**
	 * Determines how two dates compare up to no more than the specified most
	 * significant field.
	 *
	 * @param date1
	 *            the first date, not <code>null</code>
	 * @param date2
	 *            the second date, not <code>null</code>
	 * @param field
	 *            the field from <code>Calendar</code>
	 * @return diff millis
	 * @throws IllegalArgumentException
	 *             if any argument is <code>null</code>
	 * @see #truncate(Calendar, int)
	 * @see #truncatedCompareTo(Date, Date, int)
	 * @since 3.0
	 */
	public static long truncatedDiffTo(final Date date1, final Date date2, final int field) {
		final Date truncatedDate1 = truncate(date1, field);
		final Date truncatedDate2 = truncate(date2, field);
		long thisTime = truncatedDate1.getTime();
		long anotherTime = truncatedDate2.getTime();
		return Math.abs(thisTime - anotherTime);
	}

	/**
	 * Determines how two dates compare up to no more than the specified most
	 * significant field.
	 *
	 * @param date1
	 *            the first date, not <code>null</code>
	 * @param date2
	 *            the second date, not <code>null</code>
	 *            the field from <code>Calendar</code>
	 * @return diff millis
	 * @throws IllegalArgumentException
	 *             if any argument is <code>null</code>
	 * @see #truncate(Calendar, int)
	 * @see #truncatedCompareTo(Date, Date, int)
	 * @since 3.0
	 */
	public static long truncatedHourDiffTo(final Date date1, final Date date2) {
		return truncatedDiffTo(date1, date2, Calendar.HOUR) / 3600000;
	}

	/**
	 * Determines how two dates compare up to no more than the specified most
	 * significant field.
	 *
	 * @param date1
	 *            the first date, not <code>null</code>
	 * @param date2
	 *            the second date, not <code>null</code>
	 *            the field from <code>Calendar</code>
	 * @return diff millis
	 * @throws IllegalArgumentException
	 *             if any argument is <code>null</code>
	 * @see #truncate(Calendar, int)
	 * @see #truncatedCompareTo(Date, Date, int)
	 * @since 3.0
	 */
	public static long truncatedMinuteDiffTo(final Date date1, final Date date2) {
		return truncatedDiffTo(date1, date2, Calendar.MINUTE) / 60000;
	}

	/**
	 * 得到某年某周的第一天
	 *
	 * @param year
	 * @param week
	 * @return
	 */
	public static Date getFirstDayOfWeek(int year, int week) {
		week = week - 1;
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, Calendar.JANUARY);
		calendar.set(Calendar.DATE, 1);
		Calendar cal = (Calendar) calendar.clone();
		cal.add(Calendar.DATE, week * 7);

		return getFirstDayOfWeek(cal.getTime());
	}

	/**
	 * 得到某年某周的最后一天
	 *
	 * @param year
	 * @param week
	 * @return
	 */
	public static Date getLastDayOfWeek(int year, int week) {
		week = week - 1;
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, Calendar.JANUARY);
		calendar.set(Calendar.DATE, 1);
		Calendar cal = (Calendar) calendar.clone();
		cal.add(Calendar.DATE, week * 7);

		return getLastDayOfWeek(cal.getTime());
	}

	/**
	 * 取得当前日期所在周的第一天
	 *
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfWeek(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.SUNDAY);
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek()); // Sunday
		calendar.add(Calendar.DATE, 1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 取得当前日期所在周的最后一天
	 *
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfWeek(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.SUNDAY);
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek() + 6); // Saturday
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 取得当前日期所在周的前一周最后一天
	 *
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfLastWeek(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return getLastDayOfWeek(calendar.get(Calendar.YEAR), calendar.get(Calendar.WEEK_OF_YEAR) - 1);
	}

	/**
	 * 返回指定日期的月的第一天
	 *
	 * @return
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 返回指定年月的月的第一天
	 *
	 * @param year
	 * @param month
	 * @return
	 */
	public static Date getFirstDayOfMonth(Integer year, Integer month) {
		Calendar calendar = Calendar.getInstance();
		if (year == null) {
			year = calendar.get(Calendar.YEAR);
		}
		if (month == null) {
			month = calendar.get(Calendar.MONTH);
		}
		calendar.set(year, month, 1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 返回指定日期的月的最后一天
	 *
	 * @return
	 */
	public static Date getLastDayOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1);
		calendar.roll(Calendar.DATE, -1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 返回指定年月的月的最后一天
	 *
	 * @param year
	 * @param month
	 * @return
	 */
	public static Date getLastDayOfMonth(Integer year, Integer month) {
		Calendar calendar = Calendar.getInstance();
		if (year == null) {
			year = calendar.get(Calendar.YEAR);
		}
		if (month == null) {
			month = calendar.get(Calendar.MONTH);
		}
		calendar.set(year, month, 1);
		calendar.roll(Calendar.DATE, -1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 返回指定日期的上个月的最后一天
	 *
	 * @return
	 */
	public static Date getLastDayOfLastMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) - 1, 1);
		calendar.roll(Calendar.DATE, -1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 返回指定日期的季的第一天
	 *
	 * @return
	 */
	public static Date getFirstDayOfQuarter(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return getFirstDayOfQuarter(calendar.get(Calendar.YEAR), getQuarterOfYear(date));
	}

	/**
	 * 返回指定年季的季的第一天
	 *
	 * @param year
	 * @param quarter
	 * @return
	 */
	public static Date getFirstDayOfQuarter(Integer year, Integer quarter) {
		Calendar calendar = Calendar.getInstance();
		Integer month = 0;
		if (quarter == 1) {
			month = 1 - 1;
		} else if (quarter == 2) {
			month = 4 - 1;
		} else if (quarter == 3) {
			month = 7 - 1;
		} else if (quarter == 4) {
			month = 10 - 1;
		} else {
			month = calendar.get(Calendar.MONTH);
		}
		return getFirstDayOfMonth(year, month);
	}

	/**
	 * 返回指定日期的季的最后一天
	 *
	 * @return
	 */
	public static Date getLastDayOfQuarter(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return getLastDayOfQuarter(calendar.get(Calendar.YEAR), getQuarterOfYear(date));
	}

	/**
	 * 返回指定年季的季的最后一天
	 *
	 * @param year
	 * @param quarter
	 * @return
	 */
	public static Date getLastDayOfQuarter(Integer year, Integer quarter) {
		Calendar calendar = Calendar.getInstance();
		Integer month = 0;
		if (quarter == 1) {
			month = 3 - 1;
		} else if (quarter == 2) {
			month = 6 - 1;
		} else if (quarter == 3) {
			month = 9 - 1;
		} else if (quarter == 4) {
			month = 12 - 1;
		} else {
			month = calendar.get(Calendar.MONTH);
		}
		return getLastDayOfMonth(year, month);
	}

	/**
	 * 返回指定日期的上一季的最后一天
	 *
	 * @return
	 */
	public static Date getLastDayOfLastQuarter(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return getLastDayOfLastQuarter(calendar.get(Calendar.YEAR), getQuarterOfYear(date));
	}

	/**
	 * 返回指定年季的上一季的最后一天
	 *
	 * @param year
	 * @param quarter
	 * @return
	 */
	public static Date getLastDayOfLastQuarter(Integer year, Integer quarter) {
		Calendar calendar = Calendar.getInstance();
		Integer month = 0;
		if (quarter == 1) {
			month = 12 - 1;
		} else if (quarter == 2) {
			month = 3 - 1;
		} else if (quarter == 3) {
			month = 6 - 1;
		} else if (quarter == 4) {
			month = 9 - 1;
		} else {
			month = calendar.get(Calendar.MONTH);
		}
		return getLastDayOfMonth(year, month);
	}

	/**
	 * 返回指定日期的季度
	 *
	 * @param date
	 * @return
	 */
	public static int getQuarterOfYear(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.MONTH) / 3 + 1;
	}

	/**
	 * 返回昨天日期
	 * @return date
	 */
	public static Date getYesterday() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, -1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 *  返回前一年最后一天
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfLastYear(Date date) {
		Calendar calendar = Calendar.getInstance();
		return getLastDayOfYear(calendar.get(Calendar.YEAR) - 1);
	}

	/**
	 * 返回指定年的最后一天
	 * @param year
	 * @return
	 */
	public static Date getLastDayOfYear(int year) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, year - 1);
		calendar.roll(Calendar.DAY_OF_YEAR, -1);
		setMidnight(calendar);
		return calendar.getTime();
	}

	/**
	 * 格式化时间
	 * @param date
	 * @param pattern
	 * @return
	 */
	public static String formatDate(Date date, String pattern) {
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		return format.format(date);
	}

	public static String formatDateYYYYMMdd(Date date) {
		SimpleDateFormat format = new SimpleDateFormat(parsePatterns[0]);
		return format.format(date);
	}
	public static String formatDateChineseYYYYMMdd(Date date) {
		SimpleDateFormat format = new SimpleDateFormat(parsePatterns[12]);
		return format.format(date);
	}

	public static String formatDateYYYYMMddHHmm(Date date) {
		SimpleDateFormat format = new SimpleDateFormat(parsePatterns[2]);
		return format.format(date);
	}

	public static String formatDateChineseYYYYMMddHH(Date date) {
		SimpleDateFormat format = new SimpleDateFormat(parsePatterns[14]);
		return format.format(date);
	}

	/**
	 * 解析日期
	 * @param source
	 * @param pattern
	 * @return
	 * @throws ParseException
	 */
	public static Date parseDate(String source, String pattern) throws ParseException {
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		return format.parse(source);
	}

	/**
	 * 时分秒毫秒归零
	 * @param c
	 * @return
	 */
	public static Calendar setMidnight(Calendar c) {
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c;
	}

	/**
	 * 时分秒毫秒归零
	 * @return
	 */
	public static Date getEarlyToday() {
		Calendar c = Calendar.getInstance();
		setMidnight(c);
		return c.getTime();
	}

	/**
	 * 字符串转日期
	 * @param date
	 * @param format
	 * @return
	 * @throws ParseException
	 */
	public static  Date StringToDate( String date, String format) {
		Date date2;
		try {
			 date2=new SimpleDateFormat(format).parse(date);
		} catch (ParseException e) {
			throw new BusinessException("时间转换失败,date="+date,e);
		}
		return date2;
	}


	public static final String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }


	/**
	 * 增加 LocalDate ==> Date
	 */
	public static Date toDate(LocalDate temporalAccessor)
	{
		LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
		ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
		return Date.from(zdt.toInstant());
	}

	/**
	 * 日期路径 即年/月/日 如2018/08/08
	 */
	public static final String datePath()
	{
		Date now = new Date();
		return DateFormatUtils.format(now, "yyyy/MM/dd");
	}

	/**
	 * 日期型字符串转化为日期 格式
	 */
	public static Date parseDate(Object str)
	{
		if (str == null)
		{
			return null;
		}
		try
		{
			return parseDate(str.toString(), parsePatterns);
		}
		catch (ParseException e)
		{
			return null;
		}
	}

	/**
	 * 计算距离今天天数
	 * @param dates
	 * @return
	 */
	public static Integer sumDays(String dates) {
		Date date = StringToDate(dates, AFTConstants.YYYYMMDDHHMMSS);
		Date now=new Date();
		int days=(int)((now.getTime()-date.getTime())/(1000*3600*24));
		return days;
	}

	/**
	 * 获取当前时间
	 * @return
	 */
	public static LocalDate getToDay() {
        return LocalDate.now();
	}

	public static LocalDate gettomorrow() {
		LocalDate today = LocalDate.now();
        return today.plusDays(1);
	}

	public static LocalDate getFirstDayOfThisWeek() {
		LocalDate today = LocalDate.now();
        return today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
	}

	public static long getDaysBetween(Date startDate, Date endDate) {
		// 将Date转换为LocalDate（需指定时区）
		LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
		LocalDate end = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

		// 计算天数差（end - start）
		return ChronoUnit.DAYS.between(start, end);
	}


	public static void main(String[] args) {
		Date start =DateUtils.StringToDate("2025-08-05 09:00:00", AFTConstants.YYYYMMDDHHMMSS);
		Date end =DateUtils.StringToDate("2025-08-08 06:00:00", AFTConstants.YYYYMMDDHHMMSS);
		long holidays = DateUtils.getDaysBetween(start,end);
		System.out.println("holidays="+holidays);
		List<Date> list = new ArrayList<>();
		for (int i = 0; i <= holidays; i++) {
			LocalDate date = LocalDate.from(start.toInstant().atZone(ZoneId.systemDefault()));
			LocalDate localDate = date.plusDays(i);
			System.out.println(localDate);
			System.out.println(localDate.getDayOfWeek().getValue()-1);
			list.add(Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
			//获取星期
		}
	}

}
