package service

import (
	"time"

	"security-center-backend/internal/modules/caasm/collector/aws"
	caasmmodel "security-center-backend/internal/modules/caasm/model"
)

// collectorFactory holds default throttling settings to apply to collectors.
type collectorFactory struct {
	throttling caasmmodel.ThrottlingConfig
}

func newCollectorFactory() *collectorFactory {
	return &collectorFactory{
		throttling: ResolveGlobalThrottling(nil).Effective,
	}
}

func (f *collectorFactory) ConfigureThrottling(cfg caasmmodel.ThrottlingConfig) {
	f.throttling = ResolveGlobalThrottling(&cfg).Effective
}

func (f *collectorFactory) CurrentThrottling() caasmmodel.ThrottlingConfig {
	return f.throttling
}

func (f *collectorFactory) ApplyThrottling(collector *aws.AWSCollector) {
	if collector == nil {
		return
	}
	tc := f.throttling
	if !tc.Enabled {
		collector.SetThrottleEnabled(false)
		return
	}
	collector.SetThrottleEnabled(true)
	if tc.TokenCapacity > 0 || tc.TokenRefillPerSec > 0 {
		capacity := tc.TokenCapacity
		if capacity <= 0 {
			capacity = caasmmodel.DefaultThrottleTokenCapacity
		}
		refill := tc.TokenRefillPerSec
		if refill <= 0 {
			refill = caasmmodel.DefaultThrottleTokenRefillPerSec
		}
		collector.ConfigureRateLimiter(capacity, refill)
	}
	collector.ConfigureServiceLimits(tc.ServiceLimits)
	collector.ConfigureCircuitBreaker(tc.CircuitBreaker)

	threshold := tc.AdaptiveThreshold
	if threshold <= 0 {
		threshold = caasmmodel.DefaultThrottleAdaptiveThreshold
	}
	window := time.Duration(tc.AdaptiveWindowSec) * time.Second
	if window <= 0 {
		window = time.Duration(caasmmodel.DefaultThrottleAdaptiveWindowSec) * time.Second
	}
	coolOff := time.Duration(tc.CoolOffSec) * time.Second
	if coolOff <= 0 {
		coolOff = time.Duration(caasmmodel.DefaultThrottleCoolOffSec) * time.Second
	}
	maxConc := tc.MaxConcurrency
	if maxConc <= 0 {
		maxConc = caasmmodel.DefaultThrottleMaxConcurrency
	}
	minConc := tc.MinConcurrency
	if minConc <= 0 || minConc > maxConc {
		minConc = caasmmodel.DefaultThrottleMinConcurrency
	}
	collector.ConfigureAdaptive(threshold, window, coolOff, maxConc, minConc)
}
