package model

import "math"

const unlimitedRemainingQuotaMB = int64(^uint64(0) >> 1)

// PackageTrafficMetrics 套餐流量统一展示值
// 统一封装对外使用的真值、虚值和展示比例，避免各层重复实现公式。
type PackageTrafficMetrics struct {
	RealTotalMB    int64
	RealUsedMB     int64
	VirtualTotalMB int64
	VirtualUsedMB  float64
	ReductionPct   float64
}

// CalculateDisplayGainRatio 计算展示倍率
// 启用虚流量且虚总量大于 0 时，倍率 = 真总量 / 虚总量；否则退化为 1。
func CalculateDisplayGainRatio(enableVirtualData bool, realTotalMB, virtualTotalMB int64) float64 {
	if enableVirtualData && virtualTotalMB > 0 {
		return float64(realTotalMB) / float64(virtualTotalMB)
	}
	return 1.0
}

// BuildPackageUsageSnapshotValues 计算套餐使用记录应写入的快照值。
func BuildPackageUsageSnapshotValues(pkg *Package) (virtualTotalMB int64, displayGainRatio float64, enableVirtualData bool) {
	if pkg == nil {
		return 0, 1.0, false
	}

	if pkg.EnableVirtualData && pkg.VirtualDataMB > 0 {
		return pkg.VirtualDataMB, CalculateDisplayGainRatio(true, pkg.RealDataMB, pkg.VirtualDataMB), true
	}

	return pkg.RealDataMB, 1.0, false
}

// EffectiveThresholdMB 返回套餐业务耗尽阈值。
// 启用虚流量时按虚总量快照判断；否则按真总量判断。
func (u *PackageUsage) EffectiveThresholdMB() int64 {
	if u == nil {
		return 0
	}
	if u.EnableVirtualDataSnapshot && u.VirtualTotalMBSnapshot > 0 {
		return u.VirtualTotalMBSnapshot
	}
	return u.DataLimitMB
}

// RemainingQuotaMB 返回套餐剩余业务额度。
func (u *PackageUsage) RemainingQuotaMB() int64 {
	if u == nil {
		return 0
	}
	threshold := u.EffectiveThresholdMB()
	if threshold <= 0 {
		return unlimitedRemainingQuotaMB
	}
	return threshold - u.DataUsageMB
}

// IsTrafficDepleted 判断套餐是否达到业务耗尽阈值。
func (u *PackageUsage) IsTrafficDepleted() bool {
	if u == nil {
		return false
	}
	threshold := u.EffectiveThresholdMB()
	if threshold <= 0 {
		return false
	}
	return u.DataUsageMB >= threshold
}

// BuildTrafficMetrics 组装统一五字段和 reduction_pct。
func (u *PackageUsage) BuildTrafficMetrics() PackageTrafficMetrics {
	metrics := PackageTrafficMetrics{}
	if u == nil {
		return metrics
	}

	metrics.RealTotalMB = u.DataLimitMB
	metrics.RealUsedMB = u.DataUsageMB

	if u.EnableVirtualDataSnapshot && u.VirtualTotalMBSnapshot > 0 {
		metrics.VirtualTotalMB = u.VirtualTotalMBSnapshot
		metrics.VirtualUsedMB = math.Min(float64(u.DataUsageMB)*u.DisplayGainRatioSnapshot, float64(u.DataLimitMB))
		metrics.ReductionPct = u.DisplayGainRatioSnapshot - 1
		return metrics
	}

	metrics.VirtualTotalMB = u.DataLimitMB
	metrics.VirtualUsedMB = float64(u.DataUsageMB)
	metrics.ReductionPct = 0
	return metrics
}
