package v1alpha1

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

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:deepcopy-gen=true
type ContainerMomDeployment struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   ContainerMomDeploymentSpec   `json:"spec"`
	Status ContainerMomDeploymentStatus `json:"status"`
}

type ContainerMomDeploymentSpec struct {
	// Source configuration
	Source SourceSpec `json:"source"`

	// Target clusters for deployment
	Clusters []string `json:"clusters"`

	// Domain configuration
	Domain DomainSpec `json:"domain,omitempty"`

	// Resource requirements
	Resources ResourceRequirements `json:"resources"`

	// Environment variables
	Env []EnvVar `json:"env,omitempty"`

	// Billing tier
	BillingTier string `json:"billingTier"`
}

type SourceSpec struct {
	// Git repository URL
	GitURL string `json:"gitUrl,omitempty"`

	// Source to Image configuration
	BuildConfig *BuildConfig `json:"buildConfig,omitempty"`

	// Or direct container image
	Image string `json:"image,omitempty"`
}

type BuildConfig struct {
	BuilderImage string            `json:"builderImage"`
	BuildArgs    map[string]string `json:"buildArgs,omitempty"`
}

type DomainSpec struct {
	// Custom domain or use *.container.mom
	CustomDomain string `json:"customDomain,omitempty"`
	UseWildcard  bool   `json:"useWildcard,omitempty"`
	// TLS configuration
	TLS *TLSConfig `json:"tls,omitempty"`
	// DNS provider configuration for automatic DNS management
	DNSProvider *DNSProviderConfig `json:"dnsProvider,omitempty"`
}

type TLSConfig struct {
	// Use Let's Encrypt
	AutoCert bool `json:"autoCert,omitempty"`
	// Or use existing secret
	SecretName string `json:"secretName,omitempty"`
	// Email for Let's Encrypt notifications
	Email string `json:"email,omitempty"`
}

type DNSProviderConfig struct {
	// DNS provider (e.g., cloudflare, route53)
	Provider string `json:"provider"`
	// Credentials secret name
	SecretName string `json:"secretName"`
}

type ResourceRequirements struct {
	CPU    string `json:"cpu"`
	Memory string `json:"memory"`
	// Additional resource constraints
}

type EnvVar struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

type ContainerMomDeploymentStatus struct {
	Phase          string          `json:"phase,omitempty"`
	Image          string          `json:"image,omitempty"`
	Conditions     []Condition     `json:"conditions,omitempty"`
	ClusterStatus  []ClusterStatus `json:"clusterStatus,omitempty"`
	LastUpdateTime metav1.Time     `json:"lastUpdateTime,omitempty"`
}

type Condition struct {
	Type    string `json:"type"`
	Status  string `json:"status"`
	Reason  string `json:"reason,omitempty"`
	Message string `json:"message,omitempty"`
}

type ClusterStatus struct {
	Name           string `json:"name"`
	Phase          string `json:"phase"`
	URL            string `json:"url,omitempty"`
	ReadyReplicas  int32  `json:"readyReplicas"`
	CurrentVersion string `json:"currentVersion,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ContainerMomDeploymentList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`

	Items []ContainerMomDeployment `json:"items"`
}

// DeepCopy implementations for Customer
func (in *Customer) DeepCopy() *Customer {
	if in == nil {
		return nil
	}
	out := new(Customer)
	in.DeepCopyInto(out)
	return out
}

func (in *Customer) DeepCopyInto(out *Customer) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	in.Spec.DeepCopyInto(&out.Spec)
	in.Status.DeepCopyInto(&out.Status)
}

func (in *Customer) DeepCopyObject() runtime.Object {
	if in == nil {
		return nil
	}
	return in.DeepCopy()
}

// DeepCopy implementations for CustomerList
func (in *CustomerList) DeepCopy() *CustomerList {
	if in == nil {
		return nil
	}
	out := new(CustomerList)
	in.DeepCopyInto(out)
	return out
}

func (in *CustomerList) DeepCopyInto(out *CustomerList) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ListMeta.DeepCopyInto(&out.ListMeta)
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]Customer, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
}

func (in *CustomerList) DeepCopyObject() runtime.Object {
	if in == nil {
		return nil
	}
	return in.DeepCopy()
}

// DeepCopy implementations for ContainerMomDeployment
func (in *ContainerMomDeployment) DeepCopy() *ContainerMomDeployment {
	if in == nil {
		return nil
	}
	out := new(ContainerMomDeployment)
	in.DeepCopyInto(out)
	return out
}

func (in *ContainerMomDeployment) DeepCopyInto(out *ContainerMomDeployment) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	in.Spec.DeepCopyInto(&out.Spec)
	in.Status.DeepCopyInto(&out.Status)
}

func (in *ContainerMomDeployment) DeepCopyObject() runtime.Object {
	if in == nil {
		return nil
	}
	return in.DeepCopy()
}

// DeepCopy implementations for ContainerMomDeploymentList
func (in *ContainerMomDeploymentList) DeepCopy() *ContainerMomDeploymentList {
	if in == nil {
		return nil
	}
	out := new(ContainerMomDeploymentList)
	in.DeepCopyInto(out)
	return out
}

func (in *ContainerMomDeploymentList) DeepCopyInto(out *ContainerMomDeploymentList) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ListMeta.DeepCopyInto(&out.ListMeta)
	if in.Items != nil {
		in, out := &in.Items, &out.Items
		*out = make([]ContainerMomDeployment, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
}

func (in *ContainerMomDeploymentList) DeepCopyObject() runtime.Object {
	if in == nil {
		return nil
	}
	return in.DeepCopy()
}

// DeepCopyInto for CustomerSpec
func (in *CustomerSpec) DeepCopyInto(out *CustomerSpec) {
	*out = *in
	out.ResourceQuota = in.ResourceQuota
}

// DeepCopyInto for CustomerStatus
func (in *CustomerStatus) DeepCopyInto(out *CustomerStatus) {
	*out = *in
	out.UsedResources = in.UsedResources
	if in.ActiveDeployments != nil {
		in, out := &in.ActiveDeployments, &out.ActiveDeployments
		*out = make([]string, len(*in))
		copy(*out, *in)
	}
	if in.SubscriptionItems != nil {
		in, out := &in.SubscriptionItems, &out.SubscriptionItems
		*out = make(map[string]string, len(*in))
		for key, val := range *in {
			(*out)[key] = val
		}
	}
}

// DeepCopyInto for ContainerMomDeploymentSpec
func (in *ContainerMomDeploymentSpec) DeepCopyInto(out *ContainerMomDeploymentSpec) {
	*out = *in
	out.Source = in.Source
	if in.Clusters != nil {
		in, out := &in.Clusters, &out.Clusters
		*out = make([]string, len(*in))
		copy(*out, *in)
	}
	in.Domain.DeepCopyInto(&out.Domain)
	out.Resources = in.Resources
	if in.Env != nil {
		in, out := &in.Env, &out.Env
		*out = make([]EnvVar, len(*in))
		copy(*out, *in)
	}
}

// DeepCopyInto for ContainerMomDeploymentStatus
func (in *ContainerMomDeploymentStatus) DeepCopyInto(out *ContainerMomDeploymentStatus) {
	*out = *in
	if in.Conditions != nil {
		in, out := &in.Conditions, &out.Conditions
		*out = make([]Condition, len(*in))
		copy(*out, *in)
	}
	if in.ClusterStatus != nil {
		in, out := &in.ClusterStatus, &out.ClusterStatus
		*out = make([]ClusterStatus, len(*in))
		copy(*out, *in)
	}
}

// DeepCopyInto for DomainSpec
func (in *DomainSpec) DeepCopyInto(out *DomainSpec) {
	*out = *in
	if in.TLS != nil {
		in, out := &in.TLS, &out.TLS
		*out = new(TLSConfig)
		**out = **in
	}
	if in.DNSProvider != nil {
		in, out := &in.DNSProvider, &out.DNSProvider
		*out = new(DNSProviderConfig)
		**out = **in
	}
}

// DeepCopyInto for SourceSpec
func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
	*out = *in
	if in.BuildConfig != nil {
		in, out := &in.BuildConfig, &out.BuildConfig
		*out = new(BuildConfig)
		(*in).DeepCopyInto(*out)
	}
}

// DeepCopyInto for BuildConfig
func (in *BuildConfig) DeepCopyInto(out *BuildConfig) {
	*out = *in
	if in.BuildArgs != nil {
		in, out := &in.BuildArgs, &out.BuildArgs
		*out = make(map[string]string, len(*in))
		for key, val := range *in {
			(*out)[key] = val
		}
	}
}
