/*
 * SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Checkpoint storage type constants retained for compatibility with older
// operator configuration files.
const (
	CheckpointStorageTypePVC = "pvc"
	CheckpointStorageTypeS3  = "s3"
	CheckpointStorageTypeOCI = "oci"
)

// +kubebuilder:object:root=true

// OperatorConfiguration is the Schema for the operator configuration.
type OperatorConfiguration struct {
	metav1.TypeMeta `json:",inline"`

	// Server configuration (metrics, health probes, webhooks)
	Server ServerConfiguration `json:"server"`

	// Leader election configuration
	LeaderElection LeaderElectionConfiguration `json:"leaderElection"`

	// Namespace configuration (restricted vs cluster-wide)
	Namespace NamespaceConfiguration `json:"namespace"`

	// Orchestrator configuration with optional overrides
	Orchestrators OrchestratorConfiguration `json:"orchestrators"`

	// DRA (Dynamic Resource Allocation) settings with optional override
	DRA DRAConfiguration `json:"dra,omitempty"`

	// Service mesh and infrastructure addresses
	Infrastructure InfrastructureConfiguration `json:"infrastructure"`

	// Ingress configuration
	Ingress IngressConfiguration `json:"ingress"`

	// RBAC configuration for cross-namespace resource management (cluster-wide mode)
	RBAC RBACConfiguration `json:"rbac"`

	// MPI SSH secret configuration
	MPI MPIConfiguration `json:"mpi"`

	// Checkpoint/restore configuration
	Checkpoint CheckpointConfiguration `json:"checkpoint"`

	// Discovery backend configuration
	Discovery DiscoveryConfiguration `json:"discovery"`

	// GPU discovery configuration
	GPU GPUConfiguration `json:"gpu"`

	// Logging configuration
	Logging LoggingConfiguration `json:"logging"`

	// HTTP/2 and TLS settings
	Security SecurityConfiguration `json:"security"`
}

// ServerConfiguration holds server bind addresses and ports.
type ServerConfiguration struct {
	// Metrics server configuration
	// +kubebuilder:default={bindAddress: "0.0.0.0", port: 8080, secure: true}
	Metrics MetricsServer `json:"metrics"`
	// Health probe server configuration
	// +kubebuilder:default={bindAddress: "0.0.0.0", port: 8081}
	HealthProbe Server `json:"healthProbe"`
	// Webhook server configuration
	// +kubebuilder:default={host: "0.0.0.0", port: 9443, certDir: "/tmp/k8s-webhook-server/serving-certs"}
	Webhook WebhookServer `json:"webhook"`
}

// Server holds a bind address and port.
type Server struct {
	// BindAddress is the address the server binds to
	BindAddress string `json:"bindAddress"`
	// Port is the port the server listens on
	Port int `json:"port"`
}

// MetricsServer extends Server with secure serving option.
type MetricsServer struct {
	Server `json:",inline"`
	// Secure enables secure serving for the metrics endpoint.
	// nil = default to true (secure by default).
	Secure *bool `json:"secure,omitempty"`
}

// CertProvisionMode controls how webhook TLS certificates are managed.
type CertProvisionMode string

const (
	// CertProvisionModeAuto uses the built-in cert-controller to generate and rotate certificates.
	CertProvisionModeAuto CertProvisionMode = "auto"
	// CertProvisionModeManual expects certificates to be provided externally (e.g., cert-manager, admin).
	CertProvisionModeManual CertProvisionMode = "manual"
)

// WebhookServer extends Server with host and certificate directory.
type WebhookServer struct {
	Server `json:",inline"`
	// Host is the address the webhook server binds to
	Host string `json:"host"`
	// CertDir is the directory containing TLS certificates
	CertDir string `json:"certDir"`
	// CertProvisionMode controls certificate management: "auto" (built-in cert-controller) or "manual" (external)
	// +kubebuilder:default="auto"
	CertProvisionMode CertProvisionMode `json:"certProvisionMode"`
	// SecretName is the name of the Kubernetes Secret holding webhook TLS certificates
	// +kubebuilder:default="webhook-server-cert"
	SecretName string `json:"secretName"`
	// ServiceName is the name of the Kubernetes Service fronting the webhook server.
	// Used to generate certificate SANs. Set by the Helm chart.
	ServiceName string `json:"serviceName"`
}

// LeaderElectionConfiguration holds leader election settings.
type LeaderElectionConfiguration struct {
	// Enabled enables leader election for controller manager
	// +kubebuilder:default=false
	Enabled bool `json:"enabled"`
	// ID is the leader election resource identity
	ID string `json:"id"`
	// Namespace is the namespace for the leader election resource
	Namespace string `json:"namespace"`
}

// NamespaceConfiguration determines operator namespace mode.
type NamespaceConfiguration struct {
	// Deprecated: Namespace-restricted mode is deprecated and will be removed in a future release.
	// Use cluster-wide mode (leave Restricted empty) instead.
	Restricted string `json:"restricted"`
	// Deprecated: Scope is only used in namespace-restricted mode, which is deprecated.
	Scope NamespaceScopeConfiguration `json:"scope"`
}

// Deprecated: NamespaceScopeConfiguration is used only by the deprecated namespace-restricted
// mode and will be removed in a future release.
type NamespaceScopeConfiguration struct {
	// LeaseDuration is the duration of namespace scope marker lease before expiration
	// +kubebuilder:default="30s"
	LeaseDuration metav1.Duration `json:"leaseDuration"`
	// LeaseRenewInterval is the interval for renewing namespace scope marker lease
	// +kubebuilder:default="10s"
	LeaseRenewInterval metav1.Duration `json:"leaseRenewInterval"`
}

// OrchestratorConfiguration holds orchestrator override settings.
type OrchestratorConfiguration struct {
	// Grove orchestrator configuration
	Grove GroveConfiguration `json:"grove"`
	// LWS orchestrator configuration
	LWS LWSConfiguration `json:"lws"`
	// KaiScheduler configuration
	KaiScheduler KaiSchedulerConfiguration `json:"kaiScheduler"`
}

// GroveConfiguration holds Grove orchestrator settings.
type GroveConfiguration struct {
	// Enabled overrides auto-detection. nil = auto-detect.
	Enabled *bool `json:"enabled,omitempty"`
	// TerminationDelay configures the termination delay for Grove PodCliqueSets
	// +kubebuilder:default="15m"
	TerminationDelay metav1.Duration `json:"terminationDelay"`
}

// LWSConfiguration holds LWS orchestrator settings.
type LWSConfiguration struct {
	// Enabled overrides auto-detection. nil = auto-detect.
	Enabled *bool `json:"enabled,omitempty"`
}

// KaiSchedulerConfiguration holds Kai-scheduler settings.
type KaiSchedulerConfiguration struct {
	// Enabled overrides auto-detection. nil = auto-detect.
	Enabled *bool `json:"enabled,omitempty"`
}

// DRAConfiguration holds Dynamic Resource Allocation (resource.k8s.io) settings.
//
// NOTE: auto-detection here only verifies that the resource.k8s.io API group is
// registered on the apiserver (Kubernetes 1.32+). It does NOT verify that a
// GPU-specific DRA resource driver (e.g. nvidia/k8s-dra-driver-gpu) is
// installed, that its DeviceClass exists, or that node-level GPU drivers are
// compatible. An admin can use `enabled: false` to force-off DRA integration
// on clusters where the API is present but the GPU driver stack is not wired
// up — this makes the operator fail GMS / inter-pod failover admissions early
// with a clear error instead of letting pods Pend with a confusing
// "resourceclaim not found" at schedule time.
type DRAConfiguration struct {
	// Enabled overrides auto-detection of the resource.k8s.io API group.
	// nil = auto-detect. Setting true requires detection to also succeed (the
	// operator will exit at startup otherwise).
	Enabled *bool `json:"enabled,omitempty"`
}

// InfrastructureConfiguration holds service mesh and backend addresses.
type InfrastructureConfiguration struct {
	// NATSAddress is the address of the NATS server
	NATSAddress string `json:"natsAddress"`
	// ETCDAddress is the address of the etcd server
	ETCDAddress string `json:"etcdAddress"`
	// ModelExpressURL is the URL of the Model Express server to inject into all pods
	ModelExpressURL string `json:"modelExpressURL"`
	// PrometheusEndpoint is the URL of the Prometheus endpoint to use for metrics
	PrometheusEndpoint string `json:"prometheusEndpoint"`
}

// IngressConfiguration holds ingress settings.
type IngressConfiguration struct {
	// VirtualServiceGateway is the name of the Istio virtual service gateway
	VirtualServiceGateway string `json:"virtualServiceGateway"`
	// ControllerClassName is the ingress controller class name
	ControllerClassName string `json:"controllerClassName"`
	// ControllerTLSSecretName is the TLS secret for the ingress controller
	ControllerTLSSecretName string `json:"controllerTLSSecretName"`
	// HostSuffix is the suffix for ingress hostnames
	HostSuffix string `json:"hostSuffix"`
}

// UseVirtualService returns true if a VirtualService gateway is configured.
func (i *IngressConfiguration) UseVirtualService() bool {
	return i.VirtualServiceGateway != ""
}

// RBACConfiguration holds RBAC settings for cluster-wide mode.
type RBACConfiguration struct {
	// PlannerClusterRoleName is the ClusterRole for planner
	PlannerClusterRoleName string `json:"plannerClusterRoleName"`
	// DGDRProfilingClusterRoleName is the ClusterRole for DGDR profiling jobs
	DGDRProfilingClusterRoleName string `json:"dgdrProfilingClusterRoleName"`
	// EPPClusterRoleName is the ClusterRole for EPP
	EPPClusterRoleName string `json:"eppClusterRoleName"`
}

// MPIConfiguration holds MPI SSH secret settings.
type MPIConfiguration struct {
	// SSHSecretName is the name of the secret containing the SSH key for MPI
	SSHSecretName string `json:"sshSecretName"`
	// SSHSecretNamespace is the namespace where the MPI SSH secret is located
	SSHSecretNamespace string `json:"sshSecretNamespace"`
}

// CheckpointConfiguration holds checkpoint/restore settings.
type CheckpointConfiguration struct {
	// Enabled indicates if checkpoint functionality is enabled
	Enabled bool `json:"enabled"`
	// Deprecated: Storage is retained for compatibility and ignored by the
	// current snapshot flow. Snapshot storage is discovered from the
	// snapshot-agent DaemonSet instead.
	Storage CheckpointStorageConfiguration `json:"storage"`
}

// Deprecated: CheckpointStorageConfiguration is retained for compatibility and
// ignored by the current snapshot flow.
type CheckpointStorageConfiguration struct {
	// Type is the legacy storage backend type: pvc, s3, or oci.
	Type string `json:"type"`
	// PVC configuration for legacy pvc-based settings.
	PVC CheckpointPVCConfig `json:"pvc"`
	// S3 configuration for legacy s3-based settings.
	S3 CheckpointS3Config `json:"s3"`
	// OCI configuration for legacy oci-based settings.
	OCI CheckpointOCIConfig `json:"oci"`
}

// Deprecated: CheckpointPVCConfig is retained for compatibility and ignored by
// the current snapshot flow.
type CheckpointPVCConfig struct {
	// PVCName is the legacy PVC name.
	PVCName string `json:"pvcName"`
	// BasePath is the legacy base directory within the PVC.
	BasePath string `json:"basePath"`
}

// Deprecated: CheckpointS3Config is retained for compatibility and ignored by
// the current snapshot flow.
type CheckpointS3Config struct {
	// URI is the legacy S3 URI (s3://[endpoint/]bucket/prefix).
	URI string `json:"uri"`
	// CredentialsSecretRef is the legacy credentials secret name.
	CredentialsSecretRef string `json:"credentialsSecretRef"`
}

// Deprecated: CheckpointOCIConfig is retained for compatibility and ignored by
// the current snapshot flow.
type CheckpointOCIConfig struct {
	// URI is the legacy OCI URI (oci://registry/repository).
	URI string `json:"uri"`
	// CredentialsSecretRef is the legacy docker config secret name.
	CredentialsSecretRef string `json:"credentialsSecretRef"`
}

// DiscoveryConfiguration holds discovery backend settings.
type DiscoveryConfiguration struct {
	// Backend is the discovery backend: "kubernetes" or "etcd"
	// +kubebuilder:default="kubernetes"
	Backend DiscoveryBackend `json:"backend"`
}

// DiscoveryBackend is the type for the discovery backend.
type DiscoveryBackend string

const (
	// DiscoveryBackendKubernetes is the Kubernetes discovery backend
	DiscoveryBackendKubernetes DiscoveryBackend = "kubernetes"
	// DiscoveryBackendEtcd is the etcd discovery backend
	DiscoveryBackendEtcd DiscoveryBackend = "etcd"
)

// KubeDiscoveryMode is the kube discovery identity granularity.
type KubeDiscoveryMode string

const (
	// KubeDiscoveryModePod is the default: one identity per pod.
	KubeDiscoveryModePod KubeDiscoveryMode = "pod"
	// KubeDiscoveryModeContainer: each container registers independently with the discovery plane.
	KubeDiscoveryModeContainer KubeDiscoveryMode = "container"
)

// GPUConfiguration holds GPU discovery settings.
type GPUConfiguration struct {
	// DiscoveryEnabled indicates whether GPU discovery is enabled
	// +kubebuilder:default=true
	DiscoveryEnabled *bool `json:"discoveryEnabled,omitempty"`
}

// LoggingConfiguration holds logging settings.
type LoggingConfiguration struct {
	// Level is the log level (e.g., "info", "debug")
	// +kubebuilder:default="info"
	Level string `json:"level"`
	// Format is the log format (e.g., "json", "text")
	// +kubebuilder:default="json"
	Format string `json:"format"`
}

// SecurityConfiguration holds HTTP/2 and TLS settings.
type SecurityConfiguration struct {
	// EnableHTTP2 enables HTTP/2 for metrics and webhook servers
	// +kubebuilder:default=false
	EnableHTTP2 bool `json:"enableHTTP2"`
}
