package gci

import (
	"math"
	"time"
)

const (
	// GracePeriodDays is the number of days after expiry during which
	// the certificate still contributes (with declining factor)
	GracePeriodDays = 180

	// DecayStartDays is how many days before expiry the linear decay begins
	DecayStartDays = 180
)

// CalculateValidityFactor computes the validity factor for a certificate
// based on its expiry date.
//
// Rules:
// - Certificate not yet expiring (>6 months): factor = 1.0
// - Certificate expiring within 6 months: linear decay from 1.0 to 0.5
// - Certificate expired: linear decay from 0.5 to 0.0 over grace period
// - Certificate expired beyond grace period: factor = 0.0
func CalculateValidityFactor(validUntil time.Time, now time.Time) float64 {
	daysUntilExpiry := validUntil.Sub(now).Hours() / 24.0

	if daysUntilExpiry > float64(DecayStartDays) {
		// Not yet in decay window
		return 1.0
	}

	if daysUntilExpiry > 0 {
		// In pre-expiry decay window: linear from 1.0 to 0.5
		fraction := daysUntilExpiry / float64(DecayStartDays)
		return 0.5 + 0.5*fraction
	}

	// Certificate is expired
	daysExpired := -daysUntilExpiry
	if daysExpired > float64(GracePeriodDays) {
		return 0.0
	}

	// In grace period: linear from 0.5 to 0.0
	fraction := 1.0 - (daysExpired / float64(GracePeriodDays))
	return math.Max(0, 0.5*fraction)
}

// IsExpired returns true if the certificate is past its validity date
func IsExpired(validUntil time.Time, now time.Time) bool {
	return now.After(validUntil)
}

// IsExpiringSoon returns true if the certificate expires within the decay window
func IsExpiringSoon(validUntil time.Time, now time.Time) bool {
	daysUntil := validUntil.Sub(now).Hours() / 24.0
	return daysUntil > 0 && daysUntil <= float64(DecayStartDays)
}
