// Copyright Contributors to the KubeOpenCode project

package v1alpha1

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

// ContextType defines the type of context source
// +kubebuilder:validation:Enum=Text;ConfigMap;Git;Runtime;URL
type ContextType string

const (
	// ContextTypeText represents text content defined directly in YAML.
	ContextTypeText ContextType = "Text"

	// ContextTypeConfigMap represents content from a ConfigMap
	ContextTypeConfigMap ContextType = "ConfigMap"

	// ContextTypeGit represents content from a Git repository
	ContextTypeGit ContextType = "Git"

	// ContextTypeRuntime represents KubeOpenCode platform awareness context.
	// When enabled, the controller injects a system prompt that explains
	// the runtime environment to the agent.
	ContextTypeRuntime ContextType = "Runtime"

	// ContextTypeURL represents content fetched from a remote HTTP/HTTPS URL.
	// The content is fetched at task execution time via an init container.
	//
	// Use cases:
	//   - Remote API specifications (OpenAPI, GraphQL schemas)
	//   - External documentation or guidelines
	//   - Dynamic configuration from external services
	ContextTypeURL ContextType = "URL"
)

// ConfigMapContext references a ConfigMap for context content.
type ConfigMapContext struct {
	// Name of the ConfigMap
	// +required
	Name string `json:"name"`

	// Key specifies a single key to mount as a file.
	// If not specified, all keys are mounted as files in the directory.
	// +optional
	Key string `json:"key,omitempty"`

	// Optional specifies whether the ConfigMap must exist.
	// +optional
	Optional *bool `json:"optional,omitempty"`
}

// GitContext references content from a Git repository.
type GitContext struct {
	// Repository is the Git repository URL.
	// Example: "https://github.com/org/contexts"
	// +required
	Repository string `json:"repository"`

	// Path is the path within the repository to mount.
	// Can be a file or directory. If empty, the entire repository is mounted.
	//
	// Note on .git directory:
	//   - If Path is empty (entire repo): The mounted directory WILL contain .git/
	//   - If Path is specified (subdirectory): The mounted directory will NOT contain .git/
	//
	// Example: ".claude/", "docs/guide.md"
	// +optional
	Path string `json:"path,omitempty"`

	// Ref is the Git reference (branch, tag, or commit SHA).
	// Defaults to "HEAD" if not specified.
	// +optional
	// +kubebuilder:default="HEAD"
	Ref string `json:"ref,omitempty"`

	// Depth specifies the clone depth for shallow cloning.
	// 1 means shallow clone (fastest), 0 means full clone.
	// Defaults to 1 for efficiency.
	// +optional
	// +kubebuilder:default=1
	Depth *int `json:"depth,omitempty"`

	// RecurseSubmodules enables recursive cloning of Git submodules.
	// If true, submodules are initialized and cloned along with the repository.
	// Defaults to false (submodules are not cloned).
	// +optional
	RecurseSubmodules bool `json:"recurseSubmodules,omitempty"`

	// SecretRef references a Secret containing Git credentials.
	// The Secret should contain one of:
	//   - "username" + "password": For HTTPS token-based auth (password can be a PAT)
	//   - "ssh-privatekey": For SSH key-based auth
	// If not specified, anonymous clone is attempted.
	// +optional
	SecretRef *GitSecretReference `json:"secretRef,omitempty"`

	// Sync configures automatic synchronization of the Git repository.
	// Only effective for Agent contexts (ignored for Task contexts).
	// When enabled, the repository content is kept up-to-date with the remote.
	// +optional
	Sync *GitSync `json:"sync,omitempty"`
}

// GitSyncPolicy defines how Git sync changes are applied.
// +kubebuilder:validation:Enum=HotReload;Rollout
type GitSyncPolicy string

const (
	// GitSyncPolicyHotReload updates files in-place without restarting the Pod.
	// A git-sync sidecar periodically pulls changes into the shared volume.
	GitSyncPolicyHotReload GitSyncPolicy = "HotReload"

	// GitSyncPolicyRollout triggers a Deployment rolling update when changes are detected.
	// The Agent controller periodically checks the remote ref and triggers rollout on change.
	GitSyncPolicyRollout GitSyncPolicy = "Rollout"
)

// GitSync configures automatic synchronization of a Git repository.
type GitSync struct {
	// Enabled enables periodic sync of the Git repository.
	// When true, a sidecar container (HotReload) or controller polling (Rollout)
	// is used to keep the Git content up-to-date.
	// +optional
	Enabled bool `json:"enabled,omitempty"`

	// Interval is the polling interval for checking remote changes.
	// Default: "5m".
	// +optional
	Interval metav1.Duration `json:"interval,omitempty"`

	// Policy determines how changes are applied.
	// HotReload (default): sidecar pulls changes in-place, no Pod restart.
	// Rollout: controller detects changes and triggers Deployment rolling update.
	// +optional
	// +kubebuilder:default=HotReload
	Policy GitSyncPolicy `json:"policy,omitempty"`
}

// GitSecretReference references a Secret for Git authentication.
type GitSecretReference struct {
	// Name of the Secret containing Git credentials.
	// +required
	Name string `json:"name"`
}

// RuntimeContext enables KubeOpenCode platform awareness for agents.
// When enabled, the controller injects a system prompt that explains:
//   - The agent is running in a Kubernetes environment as a KubeOpenCode Task
//   - Available environment variables (TASK_NAME, TASK_NAMESPACE, WORKSPACE_DIR)
//   - How to query Task/Workflow information via kubectl
//   - Understanding of task.md structure and context mounting
//
// This context type has no configurable fields - the content is generated
// by the controller at runtime.
type RuntimeContext struct {
	// No fields - content is generated by the controller
}

// URLContext references content from a remote HTTP/HTTPS URL.
// The content is fetched at task execution time via an init container.
type URLContext struct {
	// Source is the URL to fetch content from.
	// Must be a valid HTTP or HTTPS URL.
	// +required
	Source string `json:"source"`

	// Headers specifies HTTP headers to include in the request.
	// Useful for authentication tokens or custom headers.
	// Example: {"Authorization": "Bearer token123"}
	// +optional
	Headers map[string]string `json:"headers,omitempty"`

	// SecretRef references a Secret containing authentication credentials.
	// The Secret can contain:
	//   - "token": Used as Bearer token in Authorization header
	//   - "username" + "password": Used for HTTP Basic authentication
	// If both Headers["Authorization"] and SecretRef are specified,
	// SecretRef takes precedence.
	// +optional
	SecretRef *URLSecretReference `json:"secretRef,omitempty"`

	// InsecureSkipTLSVerify skips TLS certificate verification.
	// WARNING: This is insecure and should only be used for testing
	// or with self-signed certificates in controlled environments.
	// +optional
	InsecureSkipTLSVerify bool `json:"insecureSkipTLSVerify,omitempty"`

	// Timeout specifies the request timeout in seconds.
	// Defaults to 30 seconds if not specified.
	// +optional
	// +kubebuilder:default=30
	Timeout *int32 `json:"timeout,omitempty"`
}

// URLSecretReference references a Secret for URL authentication.
type URLSecretReference struct {
	// Name of the Secret containing authentication credentials.
	// +required
	Name string `json:"name"`
}

// ContextItem defines context with content and mount path.
// Used directly in Task/Agent specs to provide additional context for task execution.
// +kubebuilder:validation:XValidation:rule="self.type != 'Text' || has(self.text)",message="text is required when type is Text"
// +kubebuilder:validation:XValidation:rule="self.type != 'ConfigMap' || has(self.configMap)",message="configMap is required when type is ConfigMap"
// +kubebuilder:validation:XValidation:rule="self.type != 'Git' || has(self.git)",message="git is required when type is Git"
// +kubebuilder:validation:XValidation:rule="self.type != 'URL' || has(self.url)",message="url is required when type is URL"
// +kubebuilder:validation:XValidation:rule="self.type != 'Git' || has(self.mountPath)",message="mountPath is required for Git context type"
type ContextItem struct {
	// === Common Fields ===

	// Name is an optional identifier for this context.
	// Used for:
	//   - Logging and debugging (clearer error messages)
	//   - XML tag generation (appears in task.md context blocks)
	//   - Context deduplication (same-named contexts can override each other)
	// If not specified, a default name is generated based on the context type and index.
	// +optional
	Name string `json:"name,omitempty"`

	// Description provides human-readable documentation for this context.
	// This is purely for documentation purposes and does not affect behavior.
	// Useful for explaining why a context is included or what it provides.
	// +optional
	Description string `json:"description,omitempty"`

	// === Type and Mount Configuration ===

	// Type of context source: Text, ConfigMap, Git, Runtime, Secret, or URL
	// +required
	Type ContextType `json:"type"`

	// MountPath specifies where this context should be mounted in the agent pod.
	//
	// Path resolution follows Tekton conventions:
	// - Absolute paths (starting with "/") are used as-is
	// - Relative paths (NOT starting with "/") are prefixed with the agent's workspaceDir
	//
	// If not specified, the content is appended to task.md with XML tags.
	//
	// Note: For Runtime context type, MountPath is ignored - content is always
	// appended to task.md.
	// +optional
	MountPath string `json:"mountPath,omitempty"`

	// FileMode is the file permission mode for the mounted file (e.g., 0755 for executable scripts).
	// Only applicable when MountPath is specified.
	// If not specified, defaults to 0644.
	// +optional
	FileMode *int32 `json:"fileMode,omitempty"`

	// === Type-Specific Fields ===

	// Text is the text content (required when Type == "Text").
	// Contains text content defined directly in YAML.
	// +optional
	Text string `json:"text,omitempty"`

	// ConfigMap context (required when Type == "ConfigMap")
	// +optional
	ConfigMap *ConfigMapContext `json:"configMap,omitempty"`

	// Git context (required when Type == "Git")
	// +optional
	Git *GitContext `json:"git,omitempty"`

	// Runtime context (optional when Type == "Runtime")
	// Enables KubeOpenCode platform awareness. The controller injects a system prompt
	// that explains the runtime environment to the agent.
	// +optional
	Runtime *RuntimeContext `json:"runtime,omitempty"`

	// URL context (required when Type == "URL")
	// Fetches content from a remote HTTP/HTTPS URL at task execution time.
	// +optional
	URL *URLContext `json:"url,omitempty"`
}
