/*
Copyright 2025.

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 (
	cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
	corev1 "k8s.io/api/core/v1"
	netowrkingv1 "k8s.io/api/networking/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.

// ArgoSyncPolicySpec defines the desired state of sync policy settings of Argo Application
type ArgoSyncPolicySpec struct {
	// Automated enables the auto sync of Argo Application
	Automated bool `json:"automated,omitempty"`
	// Prune enables the auto pruning of Argo Application
	Prune bool `json:"prune,omitempty"`
	// SelfHeal enables the auto self healing of Argo Application
	SelfHeal bool `json:"selfHeal,omitempty"`
}

// ArgoSpec defines the desired state of Argo Project and Argo Application.
type ArgoSpec struct {
	// Name of the Argo Application
	Name string `json:"name,omitempty"`
	// Name of the Argo Project
	Project string `json:"project,omitempty"`
	// Namespace of the Argo Application to deploy
	Namespace string `json:"namespace,omitempty"`
	// Branch defines the Git branch of this Argo Application
	Branch string `json:"branch,omitempty"`
	// SyncPolicy defines the sync policy settings of Argo Application
	SyncPolicy ArgoSyncPolicySpec `json:"syncPolicy,omitempty"`
}

// RepositoryType defines the type of the Git repository
type RepositoryType string

const (
	// Monorepo defines the Git repository type as monorepo
	Monorepo RepositoryType = "monorepo"
	// Separated defines the Git repository type as separated
	Separated RepositoryType = "separated"
)

// RepositoryHookEventConfigSpec defines the desired state of project's Git repository hook event configuration
type RepositoryHookEventConfigSpec struct {
	// TriggerGroups defines the groups that trigger the Git repository hook event
	TriggerGroups string `json:"triggerGroups,omitempty"`
	// ReviewersIncludesGroups defines the groups that includes the reviewers of the Git repository hook event
	ReviewersIncludesGroups string `json:"reviewersIncludesGroups,omitempty"`
}

// RepositoryHookEventSpec defines the desired state of project's Git repository hook event
type RepositoryHookEventSpec struct {
	Event string `json:"event,omitempty"`
	// Config defines the Git repository hook event configuration
	Config RepositoryHookEventConfigSpec `json:"config,omitempty"`
}

// RepositoryHookRegisterSpec defines the desired state of project's Git repository hook registration
type RepositoryHookRegisterSpec struct {
	// Enabled defines the existence of the Git repository hook registration, set to false to skip the Git repository hook registration.
	Enabled bool `json:"enabled,omitempty"`
	// Events defines the Git repository hook events
	Events []RepositoryHookEventSpec `json:"events,omitempty"`
}

const (
	// RepositoryPluginAzureDevOps defines the Git repository plugin as Azure DevOps
	RepositoryPluginAzureDevOps = "azure-devops"
)

// RepositorySpec defines the desired state of project's Git repository
type RepositorySpec struct {
	// Plugin defines the Git repository plugin
	Plugin string `json:"plugin,omitempty"`
	// PluginConfig defines the Git repository plugin configuration
	PluginConfig map[string]string `json:"pluginConfig,omitempty"`
	// RegisterToArgo defines the existence of the Git repository registration to Argo, set to false to skip the Git repository registration to Argo.
	RegisterToArgo bool `json:"registerToArgo,omitempty"`
	// Project defines the project of the Git repository
	Project string `json:"project,omitempty"`
	// Name defines the name of the Git repository
	Name string `json:"name,omitempty"`
	// Type defines the type of the Git repository
	Type RepositoryType `json:"type,omitempty"`
	// Branch defines the branch of the Git repository
	Branch string `json:"branch,omitempty"`
	// HookRegister defines the Git repository hook registration
	HookRegister RepositoryHookRegisterSpec `json:"hookRegister,omitempty"`
}

// CIExecuteModeTypes defines the type of the CI execute mode
type CIExecuteModeTypes string

const (
	// Fully defines the CI execute mode as fully
	Fully CIExecuteModeTypes = "fully"
	// OnDemand defines the CI execute mode as on-demand
	OnDemand CIExecuteModeTypes = "on-demand"
)

// CIComponentLanguage defines the type of the CI component language
type CIComponentLanguage string

const (
	// Python defines the CI component language as Python
	Python CIComponentLanguage = "python"
	// JS defines the CI component language as JavaScript
	JS CIComponentLanguage = "javascript"
)

// CIDependenciesManager defines the type of the CI dependencies manager
type CIDependenciesManager string

const (
	// PIP defines the CI dependencies manager as pip
	PIP CIDependenciesManager = "pip"
	// NPM defines the CI dependencies manager as npm
	NPM CIDependenciesManager = "npm"
	// Yarn defines the CI dependencies manager as yarn
	Yarn CIDependenciesManager = "yarn"
)

// ImageBuilderType defines the type of the image builder
type ImageBuilderType string

const (
	// DockerInDocker defines the image builder type as Docker-in-Docker
	DockerInDocker ImageBuilderType = "dind"
	// Kaniko defines the image builder type as Kaniko
	Kaniko ImageBuilderType = "kaniko"
)

// ImageRegistryCredentialType defines the type of the image registry credential
type ImageRegistryCredentialSpec struct {
	// Username defines the username of the image registry credential
	Username string `json:"username,omitempty"`
	// Password defines the password of the image registry credential
	Password string `json:"password,omitempty"`
}

type ImageRegistrySpec struct {
	// URL defines the URL of the image registry
	URL string `json:"url,omitempty"`
	// Credentials defines the credentials of the image registry
	Credentials ImageRegistryCredentialSpec `json:"credentials,omitempty"`
}

// ImageBuilderSpec defines the desired state of the image builder
type ImageBuilderSpec struct {
	// Type defines the type of the image builder
	Type ImageBuilderType `json:"type,omitempty"`
	// Registry defines the image registry of the image builder
	Registry ImageRegistrySpec `json:"registry,omitempty"`
	// Repository defines the repository of the image builder
	Repository string `json:"repository,omitempty"`
	// Name defines the name of the image builder
	Name string `json:"name,omitempty"`
	// Dockerfile defines the Dockerfile path of the image builder
	Dockerfile string `json:"dockerfile,omitempty"`
	// BuildContextRoot defines the build context root of the image builder
	BuildContextRoot string `json:"buildContextRoot,omitempty"`
	// ReleaseArchitectures defines the release architectures of the image builder
	ReleaseArchitectures []string `json:"releaseArchitectures,omitempty"`
}

// CIComponentSpec defines the desired state of CI component
type CIComponentSpec struct {
	// Name defines the name of the CI component
	Name string `json:"name,omitempty"`
	// Root defines the root path of the CI component
	Root string `json:"root,omitempty"`
	// Language defines the language of the CI component
	Language CIComponentLanguage `json:"language,omitempty"`
	// SemanticReleaseEnabled defines the existence of the semantic release, set to false to skip the semantic release.
	SemanticReleaseEnabled bool `json:"semanticReleaseEnabled,omitempty"`
	// DependenciesManager defines the dependencies manager of the CI component
	DependenciesManager CIDependenciesManager `json:"dependenciesManager,omitempty"`
	// NPMPackageJsonFile defines the path of the npm package.json file
	NPMPackageJsonFile string `json:"npmPackageJsonFile,omitempty"`
	// BuildCacheEnabled defines the existence of the build cache, set to false to skip the build caching.
	BuildCacheEnabled bool `json:"buildCacheEnabled,omitempty"`
	// BuildCommand defines the build command of the CI component
	BuildCommand string `json:"buildCommand,omitempty"`
	// BuildAgentImage defines the build agent image of the CI component
	BuildAgentImage string `json:"buildAgentImage,omitempty"`
	// BuildArtifacts defines the build artifacts of the CI component
	BuildArtifacts []string `json:"buildArtifacts,omitempty"`
	// ImageBuilder defines the image builder of the CI component
	ImageBuilder ImageBuilderSpec `json:"imageBuilder,omitempty"`
}

// ContinuousIntegrationSpec defines the desired state of Continuous Integration (CI)
type ContinuousIntegrationSpec struct {
	// ExecuteMode defines the CI execute mode
	ExecuteMode CIExecuteModeTypes `json:"executeMode,omitempty"`
	// CommitMessageLintEnabled defines the existence of the commit message lint, set to false to skip the commit message lint.
	CommitMessageLintEnabled bool `json:"commitMessageLintEnabled,omitempty"`
	// Components defines the CI components
	Components []CIComponentSpec `json:"components,omitempty"`
}

// HelmMetadataSpec defines the desired state of Helm metadata
type HelmMetadataSpec struct {
	// Name defines the name of the Helm chart
	Name string `json:"name,omitempty"`
	// Description defines the description of the Helm chart
	Description string `json:"description,omitempty"`
}

// HelmGlobalValuesSpec defines the desired state of Helm global values
type HelmGlobalValuesSpec struct {
	// Registry defines the image registry of the Helm global values
	Registry string `json:"registry,omitempty"`
	// Repository defines the repository of the Helm global values
	Repository string `json:"repository,omitempty"`
	// NodeSelector defines the node selector of the Helm global values
	NodeSelector map[string]string `json:"nodeSelector,omitempty"`
}

// HelmComponentImageSpec defines the desired state of Helm component image
type HelmComponentImageSpec struct {
	// Registry defines the image registry of the Helm component image
	Registry string `json:"registry,omitempty"`
	// Repository defines the repository of the Helm component image
	Repository string `json:"repository,omitempty"`
	// Name defines the name of the Helm component image
	Name string `json:"name,omitempty"`
	// Tag defines the tag of the Helm component image
	Tag string `json:"tag,omitempty"`
	// PullPolicy defines the pull policy of the Helm component image
	ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
}

// HelmComponentProbeType defines the type of the Helm component probe
type HelmComponentProbeType string

const (
	// HTTPGet defines the Helm component probe type as HTTP GET
	HTTPGet HelmComponentProbeType = "httpGet"
)

type HelmComponentProbeConfigSpec struct {
	// Path defines the path of the Helm component probe
	Path string `json:"path,omitempty"`
	// Port defines the port of the Helm component probe
	Port uint32 `json:"port,omitempty"`
	// InitialDelaySeconds defines the initial delay seconds of the Helm component probe
	InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"`
	// TimeoutSeconds defines the timeout seconds of the Helm component probe
	TimeoutSeconds int32 `json:"timeoutSeconds,omitempty"`
	// PeriodSeconds defines the period seconds of the Helm component probe
	PeriodSeconds int32 `json:"periodSeconds,omitempty"`
	// SuccessThreshold defines the success threshold of the Helm component probe
	SuccessThreshold int32 `json:"successThreshold,omitempty"`
	// FailureThreshold defines the failure threshold of the Helm component probe
	FailureThreshold int32 `json:"failureThreshold,omitempty"`
	// TerminationGracePeriodSeconds defines the termination grace period seconds of the Helm component probe
	TerminationGracePeriodSeconds int64 `json:"terminationGracePeriodSeconds,omitempty"`
}

// HelmComponentProbeConfigSpec defines the desired state of Helm component probe configuration
type HelmComponentProbeSpec struct {
	// Type defines the type of the Helm component probe
	Type HelmComponentProbeType `json:"type,omitempty"`
	// Config defines the configuration of the Helm component probe
	Config HelmComponentProbeConfigSpec `json:"config,omitempty"`
}

// HelmComponentProbesSpec defines the desired state of Helm component probes
type HelmComponentProbesSpec struct {
	// Liveness defines the liveness probe of the Helm component
	Liveness HelmComponentProbeSpec `json:"liveness,omitempty"`
	// Readiness defines the readiness probe of the Helm component
	Readiness HelmComponentProbeSpec `json:"readiness,omitempty"`
}

// HelmComponentServiceSpec defines the desired state of Helm component service
type HelmComponentServiceSpec struct {
	// Name defines the name of the Helm component service
	Name string `json:"name,omitempty"`
	// Type defines the type of the Helm component service
	Type corev1.ServiceType `json:"type,omitempty"`
	// Port defines the port of the Helm component service
	Port uint32 `json:"port,omitempty"`
	// TargetPort defines the target port of the Helm component service
	TargetPort uint32 `json:"targetPort,omitempty"`
}

// HelmComponentIngressTLSSpec defines the desired state of Helm component ingress TLS
type HelmComponentIngressTLSSpec struct {
	// Exists defines the existence of the Helm component ingress TLS, set to false to skip the Helm component ingress TLS auto creation.
	Exists bool `json:"exists,omitempty"`
	// Name defines the name of the Helm component ingress TLS
	Name string `json:"name,omitempty"`
	// SecretRef defines the secret reference of the Helm component ingress TLS
	SecretRef *corev1.SecretReference `json:"secretRef,omitempty"`
	// IssuerRef defines the issuer reference of the Helm component ingress TLS
	IssuerRef *cmmeta.ObjectReference `json:"issuerRef,omitempty"`
}

// HelmComponentIngressSpec defines the desired state of Helm component ingress
type HelmComponentIngressSpec struct {
	// Name defines the name of the Helm component ingress
	Name string `json:"name,omitempty"`
	// Class defines the ingress class of the Helm component ingress
	Class string `json:"class,omitempty"`
	// Host defines the host of the Helm component ingress
	Host string `json:"host,omitempty"`
	// Rules defines the route rules of the Helm component ingress
	Rules []netowrkingv1.HTTPIngressPath `json:"rules,omitempty"`
	// TLS defines the TLS of the Helm component ingress
	TLS HelmComponentIngressTLSSpec `json:"tls,omitempty"`
}

// HelmComponentConfigType defines the type of the Helm component configuration
type HelmComponentConfigType string

const (
	// EnvironmentSecret defines the Helm component configuration type as environment secret
	EnvironmentSecret HelmComponentConfigType = "environment-secret"
)

// HelmComponentConfigSpec defines the desired state of Helm component configuration
type HelmComponentConfigSpec struct {
	// Name defines the name of the Helm component configuration
	Name string `json:"name,omitempty"`
	// Type defines the type of the Helm component configuration
	Type HelmComponentConfigType `json:"type,omitempty"`
	// Data defines the data of the Helm component configuration
	Data []corev1.EnvVar `json:"data,omitempty"`
}

// HelmComponentResourceSettingSpec defines the desired state of Helm component resource setting
type HelmComponentResourceSettingSpec struct {
	// CPU defines the CPU of the Helm component resource setting
	CPU string `json:"cpu,omitempty"`
	// Memory defines the memory of the Helm component resource setting
	Memory string `json:"memory,omitempty"`
}

// HelmComponentResourceRequirementsSpec defines the desired state of Helm component resource requirements
type HelmComponentResourceRequirementsSpec struct {
	// Limits defines the limits of the Helm component resource requirements
	Limits HelmComponentResourceSettingSpec `json:"limits,omitempty"`
	// Requests defines the requests of the Helm component resource requirements
	Requests HelmComponentResourceSettingSpec `json:"requests,omitempty"`
}

// HelmComponentSpec defines the desired state of Helm component
type HelmComponentSpec struct {
	// Name defines the name of the Helm component
	Name string `json:"name,omitempty"`
	// Chart defines the chart of the Helm component
	Ports []corev1.ContainerPort `json:"ports,omitempty"`
	// Replica defines the replica of the Helm component
	Replicas uint32 `json:"replicas,omitempty"`
	// Resources defines the resources of the Helm component
	Resources HelmComponentResourceRequirementsSpec `json:"resources,omitempty"`
	// Image defines the image of the Helm component
	Image HelmComponentImageSpec `json:"image,omitempty"`
	// Probes defines the probes of the Helm component
	Probes HelmComponentProbesSpec `json:"probes,omitempty"`
	// Services defines the services of the Helm component
	Services []HelmComponentServiceSpec `json:"services,omitempty"`
	// Ingresses defines the ingresses of the Helm component
	Ingresses []HelmComponentIngressSpec `json:"ingresses,omitempty"`
	// Configs defines the configurations of the Helm component
	Configs []HelmComponentConfigSpec `json:"configs,omitempty"`
}

// HelmSpec defines the desired state of Helm generation
type HelmSpec struct {
	// Generate defines the existence of the Helm generation, set to false to skip the Helm generation.
	Generate bool `json:"generate,omitempty"`
	// Metadata defines the Helm metadata
	Metadata HelmMetadataSpec `json:"metadata,omitempty"`
	// GlobalValues defines the Helm global values
	Global HelmGlobalValuesSpec `json:"global,omitempty"`
	// Components defines the Helm components
	Components []HelmComponentSpec `json:"components,omitempty"`
}

// ProjectInitializeSpec defines the desired state of ProjectInitialize
type ProjectInitializeSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// Argo defines the desired state of Argo Project and Argo Application
	Argo *ArgoSpec `json:"argo,omitempty"`
	// Repository defines the desired state of project's Git repository
	Repository *RepositorySpec `json:"repository,omitempty"`
	// ContinuousIntegration defines the desired state of Continuous Integration (CI)
	ContinuousIntegration *ContinuousIntegrationSpec `json:"ci,omitempty"`
	// Helm defines the desired state of Helm generation
	Helm *HelmSpec `json:"helm,omitempty"`
}

const (
	// OperatorDegraded defines the ProjectInitialize condition type as OperatorDegraded
	ConditionOperatorDegraded = "OperatorDegraded"
	// RepositoryCreated defines the ProjectInitialize condition type as RepositoryCreated
	ConditionHelmPackageGenerated = "HelmPackageGenerated"
	// JenkinsfileGenerated defines the ProjectInitialize condition type as JenkinsfileGenerated
	ConditionJenkinsfileGenerated = "JenkinsfileGenerated"
	// JenkinsProjectCreated defines the ProjectInitialize condition type as JenkinsProjectCreated
	ConditionJenkinsProjectCreated = "JenkinsProjectCreated"
	// RepositoryHookConfigured defines the ProjectInitialize condition type as RepositoryHookConfigured
	ConditionRepositoryHookConfigured = "RepositoryHookConfigured"
	// ArgoProjectConfigured defines the ProjectInitialize condition type as ArgoProjectConfigured
	ConditionArgoProjectConfigured = "ArgoProjectConfigured"
	// ArgoApplicationConfigured defines the ProjectInitialize condition type as ArgoApplicationConfigured
	ConditionArgoApplicationConfigured = "ArgoApplicationConfigured"
)

const (
	// ReasonCustomResourceNotAvailable defines the reason of the ProjectInitialize condition as CustomResourceNotAvailable
	ReasonCustomResourceNotAvailable = "CustomResourceNotAvailable"
	// ReasonRepositoryCreateFailed defines the reason of the ProjectInitialize condition as RepositoryCreateFailed
	ReasonHelmPackageGenerateFailed = "HelmPackageGenerateFailed"
	// ReasonJenkinsfileGenerateFailed defines the reason of the ProjectInitialize condition as JenkinsfileGenerateFailed
	ReasonHelmPackageGenerated = "HelmPackageGenerated"
)

// ProjectInitializeStatus defines the observed state of ProjectInitialize
type ProjectInitializeStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// Conditions defines the observed conditions of the ProjectInitialize
	Conditions []metav1.Condition `json:"conditions,omitempty"`
	// Ready defines the readiness of the ProjectInitialize
	Ready bool `json:"ready,omitempty"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// ProjectInitialize is the Schema for the projectinitializes API
type ProjectInitialize struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   ProjectInitializeSpec   `json:"spec,omitempty"`
	Status ProjectInitializeStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// ProjectInitializeList contains a list of ProjectInitialize
type ProjectInitializeList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []ProjectInitialize `json:"items"`
}

func init() {
	SchemeBuilder.Register(&ProjectInitialize{}, &ProjectInitializeList{})
}
