package com.sundot.airport.common.statistics;

import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * 时间维度参数处理器
 * 处理年、季度、月等时间维度参数的计算和转换
 */
@Component
public class TimeDimensionProcessor {

    /**
     * 根据年、季度、月参数计算开始时间和结束时间
     *
     * @param params 时间维度参数
     * @return 包含开始时间和结束时间的参数对象
     */
    public TimeDimensionParams calculateTimeRange(TimeDimensionParams params) {
        LocalDate startDate = null;
        LocalDate endDate = null;

        if (params.getYear() != null) {
            if (params.getMonth() != null) {
                // 按年月计算
                startDate = LocalDate.of(params.getYear(), params.getMonth(), 1);
                endDate = startDate.withDayOfMonth(startDate.lengthOfMonth());
            } else if (params.getQuarter() != null) {
                // 按年季度计算
                int startMonth = (params.getQuarter() - 1) * 3 + 1;
                startDate = LocalDate.of(params.getYear(), startMonth, 1);
                endDate = startDate.plusMonths(2).withDayOfMonth(
                        LocalDate.of(params.getYear(), startMonth + 2, 1).lengthOfMonth());
            } else {
                // 按年计算
                startDate = LocalDate.of(params.getYear(), 1, 1);
                endDate = LocalDate.of(params.getYear(), 12, 31);
            }
        } else {
            // 如果没有指定年份，使用传入的时间范围
            if (params.getStartTime() != null && params.getEndTime() != null) {
                return params; // 直接返回原参数
            } else {
                // 默认使用当前年份
                LocalDate now = LocalDate.now();
                startDate = LocalDate.of(now.getYear(), 1, 1);
                endDate = LocalDate.of(now.getYear(), 12, 31);
            }
        }

        params.setStartTime(Date.from(startDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
        params.setEndTime(Date.from(endDate.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant()));

        return params;
    }

    /**
     * 计算环比时间范围
     *
     * @param params  原始时间参数
     * @param periods 间隔周期数
     * @return 环比时间参数
     */
    public TimeDimensionParams calculateChainRatioTimeRange(TimeDimensionParams params, int periods) {
        TimeDimensionParams chainRatioParams = new TimeDimensionParams();
        chainRatioParams.setChainRatio(true);
        chainRatioParams.setComparePeriods(periods);

        if (params.getYear() != null) {
            if (params.getMonth() != null) {
                // 按月环比
                LocalDate currentMonth = LocalDate.of(params.getYear(), params.getMonth(), 1);
                LocalDate previousMonth = currentMonth.minusMonths(periods);

                chainRatioParams.setYear(previousMonth.getYear());
                chainRatioParams.setMonth(previousMonth.getMonthValue());
            } else if (params.getQuarter() != null) {
                // 按季度环比
                int currentQuarter = params.getQuarter();
                int currentYear = params.getYear();

                // 计算上一个季度
                int totalQuarters = currentYear * 4 + currentQuarter - 1;
                totalQuarters -= periods;

                int newYear = totalQuarters / 4;
                int newQuarter = (totalQuarters % 4) + 1;

                chainRatioParams.setYear(newYear);
                chainRatioParams.setQuarter(newQuarter);
            } else {
                // 按年环比
                chainRatioParams.setYear(params.getYear() - periods);
            }
        } else if (params.getStartTime() != null && params.getEndTime() != null) {
            // 基于具体时间范围计算环比
            long diffInDays = ChronoUnit.DAYS.between(
                    params.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                    params.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) + 1;

            LocalDateTime startDateTime = params.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            LocalDateTime endDateTime = params.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

            LocalDateTime chainStart = startDateTime.minusDays(diffInDays * periods);
            LocalDateTime chainEnd = endDateTime.minusDays(diffInDays * periods);

            chainRatioParams.setStartTime(Date.from(chainStart.atZone(ZoneId.systemDefault()).toInstant()));
            chainRatioParams.setEndTime(Date.from(chainEnd.atZone(ZoneId.systemDefault()).toInstant()));
        }

        return chainRatioParams;
    }

    /**
     * 计算同比时间范围
     *
     * @param params 原始时间参数
     * @return 同比时间参数
     */
    public TimeDimensionParams calculateYearOnYearTimeRange(TimeDimensionParams params) {
        TimeDimensionParams yearOnYearParams = new TimeDimensionParams();
        yearOnYearParams.setYearOnYear(true);

        if (params.getYear() != null) {
            if (params.getMonth() != null) {
                // 按月同比
                yearOnYearParams.setYear(params.getYear() - 1);
                yearOnYearParams.setMonth(params.getMonth());
            } else if (params.getQuarter() != null) {
                // 按季度同比
                yearOnYearParams.setYear(params.getYear() - 1);
                yearOnYearParams.setQuarter(params.getQuarter());
            } else {
                // 按年同比
                yearOnYearParams.setYear(params.getYear() - 1);
            }
        } else if (params.getStartTime() != null && params.getEndTime() != null) {
            // 基于具体时间范围计算同比
            LocalDateTime startDateTime = params.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            LocalDateTime endDateTime = params.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

            LocalDateTime yearOnYearStart = startDateTime.minusYears(1);
            LocalDateTime yearOnYearEnd = endDateTime.minusYears(1);

            yearOnYearParams.setStartTime(Date.from(yearOnYearStart.atZone(ZoneId.systemDefault()).toInstant()));
            yearOnYearParams.setEndTime(Date.from(yearOnYearEnd.atZone(ZoneId.systemDefault()).toInstant()));
        }

        return yearOnYearParams;
    }
}