package runtimeconfig

import (
	apiconfig "github.com/sandbox0-ai/sandbox0/infra-operator/api/config"
	infrav1alpha1 "github.com/sandbox0-ai/sandbox0/infra-operator/api/v1alpha1"
)

func ToManager(spec *infrav1alpha1.ManagerConfig) *apiconfig.ManagerConfig {
	cfg := &apiconfig.ManagerConfig{}
	if spec == nil {
		return cfg
	}
	webhookOutboxDir := ""
	if spec.ProcdConfig.WebhookOutboxDir != nil {
		webhookOutboxDir = *spec.ProcdConfig.WebhookOutboxDir
	}

	cfg.HTTPPort = spec.HTTPPort
	cfg.KubeConfig = spec.KubeConfig
	cfg.K8sClientQPS = spec.K8sClientQPS
	cfg.K8sClientBurst = spec.K8sClientBurst
	cfg.LeaderElection = spec.LeaderElection
	cfg.ResyncPeriod = spec.ResyncPeriod
	cfg.DatabaseMaxConns = spec.DatabaseMaxConns
	cfg.DatabaseMinConns = spec.DatabaseMinConns
	cfg.CleanupInterval = spec.CleanupInterval
	cfg.LogLevel = spec.LogLevel
	cfg.MetricsPort = spec.MetricsPort
	cfg.WebhookPort = spec.WebhookPort
	cfg.WebhookCertPath = spec.WebhookCertPath
	cfg.WebhookKeyPath = spec.WebhookKeyPath
	cfg.DefaultSandboxTTL = spec.DefaultSandboxTTL
	cfg.TeamTemplateMemoryPerCPU = spec.TeamTemplateMemoryPerCPU
	cfg.SandboxMaxMemory = spec.SandboxMaxMemory
	cfg.SandboxRuntimeClassName = spec.SandboxRuntimeClassName
	cfg.ProcdBinImageRef = spec.ProcdBinImageRef
	cfg.DefaultTeamQuotas = cloneTeamQuotaLimitConfigs(spec.DefaultTeamQuotas)
	cfg.AllowColdStartWithoutReadyDataPlane = spec.AllowColdStartWithoutReadyDataPlane
	cfg.NetdPolicyApplyTimeout = spec.NetdPolicyApplyTimeout
	cfg.NetdPolicyApplyPollInterval = spec.NetdPolicyApplyPollInterval
	cfg.EgressAuthDefaultResolveTTL = spec.EgressAuthDefaultResolveTTL
	cfg.PauseMinMemoryRequest = spec.PauseMinMemoryRequest
	cfg.PauseMinMemoryLimit = spec.PauseMinMemoryLimit
	cfg.PauseMemoryBufferRatio = spec.PauseMemoryBufferRatio
	cfg.PauseMinCPU = spec.PauseMinCPU
	cfg.ProcdClientTimeout = spec.ProcdClientTimeout
	cfg.ProcdInitTimeout = spec.ProcdInitTimeout
	cfg.ShutdownTimeout = spec.ShutdownTimeout
	cfg.ProcdConfig = apiconfig.ProcdConfig{
		HTTPPort:               spec.ProcdConfig.HTTPPort,
		LogLevel:               spec.ProcdConfig.LogLevel,
		RootPath:               spec.ProcdConfig.RootPath,
		ContextCleanupInterval: spec.ProcdConfig.ContextCleanupInterval,
		ContextIdleTimeout:     spec.ProcdConfig.ContextIdleTimeout,
		ContextMaxLifetime:     spec.ProcdConfig.ContextMaxLifetime,
		ContextFinishedTTL:     spec.ProcdConfig.ContextFinishedTTL,
		WebhookQueueSize:       spec.ProcdConfig.WebhookQueueSize,
		WebhookRequestTimeout:  spec.ProcdConfig.WebhookRequestTimeout,
		WebhookMaxRetries:      spec.ProcdConfig.WebhookMaxRetries,
		WebhookBaseBackoff:     spec.ProcdConfig.WebhookBaseBackoff,
		WebhookOutboxDir:       webhookOutboxDir,
	}
	cfg.Autoscaler = apiconfig.AutoscalerConfig{
		MinScaleInterval:        spec.Autoscaler.MinScaleInterval,
		ScaleUpFactor:           spec.Autoscaler.ScaleUpFactor,
		MaxScaleStep:            spec.Autoscaler.MaxScaleStep,
		MinIdleBuffer:           spec.Autoscaler.MinIdleBuffer,
		TargetIdleRatio:         spec.Autoscaler.TargetIdleRatio,
		NoTrafficScaleDownAfter: spec.Autoscaler.NoTrafficScaleDownAfter,
		ScaleDownPercent:        spec.Autoscaler.ScaleDownPercent,
	}
	return cfg
}

func cloneTeamQuotaLimitConfigs(in []infrav1alpha1.TeamQuotaLimitConfig) []apiconfig.TeamQuotaLimitConfig {
	if len(in) == 0 {
		return nil
	}
	out := make([]apiconfig.TeamQuotaLimitConfig, 0, len(in))
	for _, limit := range in {
		out = append(out, apiconfig.TeamQuotaLimitConfig{
			Dimension:  limit.Dimension,
			LimitValue: limit.LimitValue,
		})
	}
	return out
}

func ToStorageProxy(spec *infrav1alpha1.StorageProxyConfig) *apiconfig.StorageProxyConfig {
	cfg := &apiconfig.StorageProxyConfig{ObjectEncryptionEnabled: true}
	if spec == nil {
		return cfg
	}

	cfg.HTTPAddr = spec.HTTPAddr
	cfg.HTTPPort = spec.HTTPPort
	cfg.DatabaseMaxConns = spec.DatabaseMaxConns
	cfg.DatabaseMinConns = spec.DatabaseMinConns
	cfg.DatabaseSchema = spec.DatabaseSchema
	cfg.FilesystemName = spec.FilesystemName
	cfg.FilesystemBlockSize = spec.FilesystemBlockSize
	cfg.FilesystemCompression = spec.FilesystemCompression
	cfg.FilesystemTrashDays = spec.FilesystemTrashDays
	cfg.FilesystemMetaRetries = spec.FilesystemMetaRetries
	cfg.FilesystemMaxUpload = spec.FilesystemMaxUpload
	cfg.S0FSSegmentTargetSize = spec.S0FSSegmentTargetSize
	cfg.S0FSCompactionInterval = spec.S0FSCompactionInterval
	cfg.S0FSCompactionMinDeadRatio = spec.S0FSCompactionMinDeadRatio
	cfg.S0FSCompactionMinReclaimSize = spec.S0FSCompactionMinReclaimSize
	cfg.ObjectEncryptionEnabled = spec.ObjectEncryptionEnabled
	cfg.ObjectEncryptionPassphrase = spec.ObjectEncryptionPassphrase
	cfg.ObjectEncryptionAlgo = spec.ObjectEncryptionAlgo
	cfg.FilesystemAttrTimeout = spec.FilesystemAttrTimeout
	cfg.FilesystemEntryTimeout = spec.FilesystemEntryTimeout
	cfg.FilesystemDirEntryTimeout = spec.FilesystemDirEntryTimeout
	cfg.HeartbeatInterval = spec.HeartbeatInterval
	cfg.HeartbeatTimeout = spec.HeartbeatTimeout
	cfg.FlushTimeout = spec.FlushTimeout
	cfg.CleanupInterval = spec.CleanupInterval
	cfg.DirectVolumeFileIdleTTL = spec.DirectVolumeFileIdleTTL
	cfg.CacheDir = spec.CacheDir
	cfg.CacheSizeLimit = spec.CacheSizeLimit
	cfg.LogSizeLimit = spec.LogSizeLimit
	cfg.VolumePortalCacheSizeLimit = spec.VolumePortalCacheSizeLimit
	cfg.VolumePortalRootMinFree = spec.VolumePortalRootMinFree
	cfg.MetricsEnabled = spec.MetricsEnabled
	cfg.MetricsPort = spec.MetricsPort
	cfg.LogLevel = spec.LogLevel
	cfg.AuditLog = spec.AuditLog
	cfg.AuditFile = spec.AuditFile
	cfg.HTTPReadTimeout = spec.HTTPReadTimeout
	cfg.HTTPWriteTimeout = spec.HTTPWriteTimeout
	cfg.HTTPIdleTimeout = spec.HTTPIdleTimeout
	cfg.MaxOpsPerSecond = spec.MaxOpsPerSecond
	cfg.MaxBytesPerSecond = spec.MaxBytesPerSecond
	cfg.WatchEventsEnabled = spec.WatchEventsEnabled
	cfg.WatchEventQueueSize = spec.WatchEventQueueSize
	cfg.RestoreRemountTimeout = spec.RestoreRemountTimeout
	cfg.KubeconfigPath = spec.KubeconfigPath
	return cfg
}

func ToNetd(spec *infrav1alpha1.NetdConfig) *apiconfig.NetdConfig {
	cfg := &apiconfig.NetdConfig{}
	if spec == nil {
		return cfg
	}

	cfg.LogLevel = spec.LogLevel
	cfg.NodeName = spec.NodeName
	cfg.EgressAuthResolverURL = spec.EgressAuthResolverURL
	cfg.EgressAuthEnabled = spec.EgressAuthEnabled
	cfg.EgressAuthResolverTimeout = spec.EgressAuthResolverTimeout
	cfg.EgressAuthFailurePolicy = spec.EgressAuthFailurePolicy
	cfg.MITMLeafTTL = spec.MITMLeafTTL
	cfg.ResyncPeriod = spec.ResyncPeriod
	cfg.MetricsPort = spec.MetricsPort
	cfg.HealthPort = spec.HealthPort
	cfg.FailClosed = spec.FailClosed
	cfg.PreferNFT = cloneBoolPointer(spec.PreferNFT)
	cfg.BurstRatio = spec.BurstRatio
	cfg.ProxyListenAddr = spec.ProxyListenAddr
	cfg.ProxyHTTPPort = spec.ProxyHTTPPort
	cfg.ProxyHTTPSPort = spec.ProxyHTTPSPort
	cfg.ProxyHeaderLimit = spec.ProxyHeaderLimit
	cfg.ProxyUpstreamTimeout = spec.ProxyUpstreamTimeout
	cfg.EgressBandwidthBytesPerSecond = spec.EgressBandwidthBytesPerSecond
	cfg.IngressBandwidthBytesPerSecond = spec.IngressBandwidthBytesPerSecond
	cfg.BandwidthBurstBytes = spec.BandwidthBurstBytes
	cfg.TeamEgressBandwidthBytesPerSecond = spec.TeamEgressBandwidthBytesPerSecond
	cfg.TeamIngressBandwidthBytesPerSecond = spec.TeamIngressBandwidthBytesPerSecond
	cfg.TeamBandwidthBurstBytes = spec.TeamBandwidthBurstBytes
	cfg.DNSPort = spec.DNSPort
	cfg.PlatformAllowedCIDRs = cloneStrings(spec.PlatformAllowedCIDRs)
	cfg.PlatformDeniedCIDRs = cloneStrings(spec.PlatformDeniedCIDRs)
	cfg.PlatformAllowedDomains = cloneStrings(spec.PlatformAllowedDomains)
	cfg.PlatformDeniedDomains = cloneStrings(spec.PlatformDeniedDomains)
	cfg.UseEBPF = spec.UseEBPF
	cfg.BPFFSPath = spec.BPFFSPath
	cfg.BPFPinPath = spec.BPFPinPath
	cfg.UseEDT = spec.UseEDT
	cfg.EDTHorizon = spec.EDTHorizon
	cfg.VethPrefix = spec.VethPrefix
	cfg.MetricsReportInterval = spec.MetricsReportInterval
	cfg.MeteringReportInterval = spec.MeteringReportInterval
	cfg.AuditLogPath = spec.AuditLogPath
	cfg.AuditLogMaxBytes = spec.AuditLogMaxBytes
	cfg.AuditLogMaxBackups = spec.AuditLogMaxBackups
	cfg.ShutdownDelay = spec.ShutdownDelay
	return cfg
}

func cloneBoolPointer(src *bool) *bool {
	if src == nil {
		return nil
	}
	value := *src
	return &value
}
