package com.pig4cloud.pig.common.core.util.stat;


import lombok.extern.slf4j.Slf4j;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: lwh
 * @date: 2025-08-25
 * @description: 统计模块时间工具类
 */
@Slf4j
public class TimeUtil {

	/**
	 * 根据时间粒度和日期字符串获取开始时间
	 */
	public static LocalDateTime getStartTime(String dateStr, String timeUnit) {
		try {
			return switch (timeUnit) {
				case "hour" -> {
					DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00");
					yield LocalDateTime.parse(dateStr, formatter);
				}
				case "day", "week", "month" -> {
					DateTimeFormatter day = DateTimeFormatter.ofPattern("yyyy-MM-dd");
					yield LocalDate.parse(dateStr, day).atStartOfDay();
				}
				default -> {
					log.warn("不支持的时间粒度: {}", timeUnit);
					yield null;
				}
			};
		} catch (DateTimeParseException e) {
			log.error("日期解析失败, date: {}, timeUnit: {}", dateStr, timeUnit, e);
			return null;
		}
	}

	/**
	 * 根据时间粒度和日期字符串获取结束时间
	 */
	public static LocalDateTime getEndTime(String dateStr, String timeUnit) {
		try {
			switch (timeUnit) {
				case "hour":
					DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00");
					return LocalDateTime.parse(dateStr, formatter).plusHours(1);
				case "day":
					DateTimeFormatter day = DateTimeFormatter.ofPattern("yyyy-MM-dd");
					return LocalDate.parse(dateStr, day).atStartOfDay().plusDays(1);
				case "week":
					DateTimeFormatter week = DateTimeFormatter.ofPattern("yyyy-MM-dd");
					return LocalDate.parse(dateStr, week).atStartOfDay().plusWeeks(1);
				case "month":
					DateTimeFormatter month = DateTimeFormatter.ofPattern("yyyy-MM-dd");
					LocalDate startDate = LocalDate.parse(dateStr, month);
					return startDate.plusMonths(1).atStartOfDay();
				default:
					log.warn("不支持的时间粒度: {}", timeUnit);
					return null;
			}
		} catch (DateTimeParseException e) {
			log.error("日期解析失败, date: {}, timeUnit: {}", dateStr, timeUnit, e);
			return null;
		}
	}

	/**
	 * 生成时间轴列表
	 */
	public static List<String> generateTimeAxis(LocalDate fromDate, LocalDate toDate, String timeUnit) {
		List<String> timeAxis = new ArrayList<>();
		DateTimeFormatter formatter;

		switch (timeUnit) {
			case "hour":
				formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00");
				LocalDateTime startHour = fromDate.atStartOfDay();
				LocalDateTime endHour = toDate.atTime(23, 0);

				while (!startHour.isAfter(endHour)) {
					timeAxis.add(startHour.format(formatter));
					startHour = startHour.plusHours(1);
				}
				break;

			case "day":
				formatter = DateTimeFormatter.ISO_LOCAL_DATE;
				LocalDate currentDay = fromDate;

				while (!currentDay.isAfter(toDate)) {
					timeAxis.add(currentDay.format(formatter));
					currentDay = currentDay.plusDays(1);
				}
				break;

			case "week":
				formatter = DateTimeFormatter.ISO_LOCAL_DATE;
				LocalDate firstSunday = fromDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
				LocalDate lastSunday = toDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
				LocalDate currentSunday = firstSunday;
				while (!currentSunday.isAfter(lastSunday)) {
					timeAxis.add(currentSunday.format(formatter));
					currentSunday = currentSunday.plusWeeks(1);
				}
				break;

			case "month":
				formatter = DateTimeFormatter.ISO_LOCAL_DATE;
				LocalDate firstDayOfMonth = fromDate.with(TemporalAdjusters.firstDayOfMonth());
				LocalDate lastDayOfMonth = toDate.with(TemporalAdjusters.firstDayOfMonth());

				LocalDate currentMonth = firstDayOfMonth;
				while (!currentMonth.isAfter(lastDayOfMonth)) {
					timeAxis.add(currentMonth.format(formatter));
					currentMonth = currentMonth.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
				}
				break;

			default:
				throw new IllegalArgumentException("不支持的时间单位: " + timeUnit);
		}

		return timeAxis;
	}

	/**
	 * 生成指定分页的时间坐标轴
	 */
	public static List<String> generatePageTimeAxis(LocalDate fromDate, LocalDate toDate, String timeUnit, long current, long size) {
		List<String> timeAxis = new ArrayList<>();
		DateTimeFormatter formatter;

		// 计算起始位置
		long startPosition = (current - 1) * size;
		long currentPosition = 0;

		switch (timeUnit) {
			case "hour":
				formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00");
				LocalDateTime startHour = fromDate.atStartOfDay();
				LocalDateTime endHour = toDate.atTime(23, 0);

				// 跳过前面页的数据
				while (!startHour.isAfter(endHour) && currentPosition < startPosition) {
					startHour = startHour.plusHours(1);
					currentPosition++;
				}

				// 收集当前页的数据
				while (!startHour.isAfter(endHour) && timeAxis.size() < size) {
					timeAxis.add(startHour.format(formatter));
					startHour = startHour.plusHours(1);
				}
				break;

			case "day":
				formatter = DateTimeFormatter.ISO_LOCAL_DATE;
				LocalDate currentDay = fromDate;

				// 跳过前面页的数据
				while (!currentDay.isAfter(toDate) && currentPosition < startPosition) {
					currentDay = currentDay.plusDays(1);
					currentPosition++;
				}

				// 收集当前页的数据
				while (!currentDay.isAfter(toDate) && timeAxis.size() < size) {
					timeAxis.add(currentDay.format(formatter));
					currentDay = currentDay.plusDays(1);
				}
				break;

			case "week":
				formatter = DateTimeFormatter.ISO_LOCAL_DATE;
				LocalDate firstSunday = fromDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
				LocalDate lastSunday = toDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
				LocalDate currentSunday = firstSunday;

				// 跳过前面页的数据
				while (!currentSunday.isAfter(lastSunday) && currentPosition < startPosition) {
					currentSunday = currentSunday.plusWeeks(1);
					currentPosition++;
				}

				// 收集当前页的数据
				while (!currentSunday.isAfter(lastSunday) && timeAxis.size() < size) {
					timeAxis.add(currentSunday.format(formatter));
					currentSunday = currentSunday.plusWeeks(1);
				}
				break;

			case "month":
				formatter = DateTimeFormatter.ISO_LOCAL_DATE;
				LocalDate firstDayOfMonth = fromDate.with(TemporalAdjusters.firstDayOfMonth());
				LocalDate lastDayOfMonth = toDate.with(TemporalAdjusters.firstDayOfMonth());

				LocalDate currentMonth = firstDayOfMonth;

				// 跳过前面页的数据
				while (!currentMonth.isAfter(lastDayOfMonth) && currentPosition < startPosition) {
					currentMonth = currentMonth.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
					currentPosition++;
				}

				// 收集当前页的数据
				while (!currentMonth.isAfter(lastDayOfMonth) && timeAxis.size() < size) {
					timeAxis.add(currentMonth.format(formatter));
					currentMonth = currentMonth.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
				}
				break;

			default:
				throw new IllegalArgumentException("不支持的时间单位: " + timeUnit);
		}

		return timeAxis;
	}

	/**
	 * 计算总记录数(用于分页)
	 */
	public static long calculateTotalCount(LocalDate fromDate, LocalDate toDate, String timeUnit) {
		switch (timeUnit) {
			case "hour":
				// 计算小时数: 天数差 * 24 + 结束日小时数 - 开始日小时数 + 1
				long days = ChronoUnit.DAYS.between(fromDate, toDate);
				return days * 24 + 24; // 每天24小时

			case "day":
				// 计算天数
				return ChronoUnit.DAYS.between(fromDate, toDate) + 1;

			case "week":
				// 计算周数
				LocalDate firstSunday = fromDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
				LocalDate lastSunday = toDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
				return ChronoUnit.WEEKS.between(firstSunday, lastSunday) + 1;

			case "month":
				// 计算月数：基于月份第一天计算，与generatePageTimeAxis逻辑保持一致
				LocalDate firstMonDay = fromDate.with(TemporalAdjusters.firstDayOfMonth());
				LocalDate lastMonDay = toDate.with(TemporalAdjusters.firstDayOfMonth());
				return ChronoUnit.MONTHS.between(firstMonDay, lastMonDay) + 1;

			default:
				throw new IllegalArgumentException("不支持的时间单位: " + timeUnit);
		}
	}


}
