package packagepkg

import (
	"time"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
)

// CalculateExpiryTime 计算套餐过期时间
// calendarType: 套餐周期类型（natural_month=自然月，by_day=按天）
// activatedAt: 激活时间
// durationMonths: 套餐时长（月数，calendar_type=natural_month 时使用）
// durationDays: 套餐天数（calendar_type=by_day 时使用，兼容每月折算天数）
// 返回：过期时间（当天 23:59:59）
func CalculateExpiryTime(calendarType string, activatedAt time.Time, durationMonths, durationDays int) time.Time {
	var expiryDate time.Time

	if calendarType == constants.PackageCalendarTypeNaturalMonth {
		// 自然月套餐：activated_at 月份 + N 个月，月末 23:59:59
		// 计算目标年月
		targetYear := activatedAt.Year()
		targetMonth := activatedAt.Month() + time.Month(durationMonths)

		// 处理月份溢出
		for targetMonth > 12 {
			targetMonth -= 12
			targetYear++
		}

		// 获取目标月份的最后一天（下个月的第0天就是本月最后一天）
		expiryDate = time.Date(targetYear, targetMonth+1, 0, 23, 59, 59, 0, activatedAt.Location())
	} else {
		// 按天套餐：activated_at + N 天，23:59:59
		effectiveDays := calculateByDayValidityDays(durationMonths, durationDays)
		expiryDate = activatedAt.AddDate(0, 0, effectiveDays)
		expiryDate = time.Date(expiryDate.Year(), expiryDate.Month(), expiryDate.Day(), 23, 59, 59, 0, expiryDate.Location())
	}

	return expiryDate
}

// CalculateValidityDays 计算套餐展示有效天数。
// 按天套餐优先返回折算后的总天数；自然月套餐按 baseTime 推算到目标月月末。
func CalculateValidityDays(calendarType string, baseTime time.Time, durationMonths, durationDays int) int {
	if calendarType == constants.PackageCalendarTypeNaturalMonth {
		return calculateNaturalMonthValidityDays(baseTime, durationMonths)
	}
	return calculateByDayValidityDays(durationMonths, durationDays)
}

func calculateByDayValidityDays(durationMonths, durationDays int) int {
	if durationDays <= 0 {
		if durationMonths <= 0 {
			return 0
		}
		return durationMonths * 30
	}

	if durationMonths > 1 && durationDays <= 31 {
		return durationMonths * durationDays
	}

	return durationDays
}

func calculateNaturalMonthValidityDays(baseTime time.Time, durationMonths int) int {
	if baseTime.IsZero() || durationMonths <= 0 {
		return 0
	}

	expiresAt := CalculateExpiryTime(constants.PackageCalendarTypeNaturalMonth, baseTime, durationMonths, 0)
	startDate := time.Date(baseTime.Year(), baseTime.Month(), baseTime.Day(), 0, 0, 0, 0, baseTime.Location())
	endDate := time.Date(expiresAt.Year(), expiresAt.Month(), expiresAt.Day(), 0, 0, 0, 0, expiresAt.Location())
	days := int(endDate.Sub(startDate).Hours()/24) + 1
	if days < 0 {
		return 0
	}
	return days
}

// CalculateNextResetTime 计算下次流量重置时间
// dataResetCycle: 流量重置周期（daily/monthly/yearly/none）
// calendarType: 套餐周期类型（natural_month/by_day），影响月重置逻辑
// currentTime: 当前时间
// activatedAt: 套餐激活时间（按天套餐月重置时使用）
// 返回：下次重置时间（00:00:00）
func CalculateNextResetTime(dataResetCycle, calendarType string, currentTime, activatedAt time.Time) *time.Time {
	if dataResetCycle == constants.PackageDataResetNone {
		// 不重置
		return nil
	}

	var nextResetTime time.Time

	switch dataResetCycle {
	case constants.PackageDataResetDaily:
		// 日重置：明天 00:00:00
		nextResetTime = time.Date(
			currentTime.Year(),
			currentTime.Month(),
			currentTime.Day()+1,
			0, 0, 0, 0,
			currentTime.Location(),
		)

	case constants.PackageDataResetMonthly:
		if calendarType == constants.PackageCalendarTypeNaturalMonth {
			// 自然月套餐：每月1号 00:00:00 重置
			year := currentTime.Year()
			month := currentTime.Month()

			// 如果当前日期 >= 1号（即已过重置点），则下次重置为下个月1号
			if currentTime.Day() >= 1 {
				month++
				if month > 12 {
					month = 1
					year++
				}
			}

			nextResetTime = time.Date(year, month, 1, 0, 0, 0, 0, currentTime.Location())
		} else {
			// 按天套餐：从激活日期开始，每30天重置一次
			// 计算从激活到现在经过了多少个30天周期
			daysSinceActivation := int(currentTime.Sub(activatedAt).Hours() / 24)
			cyclesPassed := daysSinceActivation / 30

			// 下次重置时间 = 激活时间 + (已过周期数+1) * 30天
			nextResetTime = activatedAt.AddDate(0, 0, (cyclesPassed+1)*30)
			nextResetTime = time.Date(
				nextResetTime.Year(),
				nextResetTime.Month(),
				nextResetTime.Day(),
				0, 0, 0, 0,
				nextResetTime.Location(),
			)
		}

	case constants.PackageDataResetYearly:
		// 年重置：每年1月1日 00:00:00
		year := currentTime.Year()

		// 如果当前日期已经过了1月1日，则使用明年
		jan1ThisYear := time.Date(year, 1, 1, 0, 0, 0, 0, currentTime.Location())
		if currentTime.After(jan1ThisYear) || currentTime.Equal(jan1ThisYear) {
			year++
		}

		nextResetTime = time.Date(year, 1, 1, 0, 0, 0, 0, currentTime.Location())

	default:
		return nil
	}

	return &nextResetTime
}
