// Package domain contains pure domain models with no external dependencies.
package domain

import "time"

// DeploySpec defines a deployment request.
type DeploySpec struct {
	ProjectName   string            // Project identifier
	ComponentPath string            // Component path within monorepo (e.g., "services/auth-api"), empty for single-app projects
	Image         string            // Container image (e.g., zot.threesix.svc:5000/myapp:latest)
	Domain        string            // Domain for ingress (e.g., myapp.threesix.ai)
	Port          int               // Container port to expose
	Replicas      int               // Number of replicas
	EnvVars       map[string]string // Plain environment variables
	Secrets       map[string]string // Secret environment variables (stored in K8s Secret)
	BasePath      string            // URL path prefix for Ingress (e.g., "/api/auth", "/"); empty defaults to "/"

	// SiblingServices maps environment variable names to internal service URLs.
	// Used for service discovery - each component gets env vars for all sibling services.
	// Example: {"AUTH_SVC_URL": "http://myproject-auth-svc:8001", "CHAT_SVC_URL": "http://myproject-chat-svc:8002"}
	SiblingServices map[string]string
}

// DeploymentName returns the K8s resource name for this deployment.
// For monorepo components, it's "{project}-{component}", for single apps it's just "{project}".
func (s DeploySpec) DeploymentName() string {
	if s.ComponentPath == "" {
		return s.ProjectName
	}
	// Extract component name from path (e.g., "services/auth-api" -> "auth-api")
	parts := splitPath(s.ComponentPath)
	if len(parts) > 0 {
		return s.ProjectName + "-" + parts[len(parts)-1]
	}
	return s.ProjectName
}

// splitPath splits a path like "services/auth-api" into ["services", "auth-api"].
func splitPath(path string) []string {
	var parts []string
	current := ""
	for _, c := range path {
		if c == '/' {
			if current != "" {
				parts = append(parts, current)
				current = ""
			}
		} else {
			current += string(c)
		}
	}
	if current != "" {
		parts = append(parts, current)
	}
	return parts
}

// DeployStatus represents the current state of a deployment.
type DeployStatus struct {
	ProjectName   string
	ComponentPath string // Component path if this is a component deployment
	Image         string
	Replicas      int
	ReadyReplicas int
	URL           string
	Status        DeploymentStatus
	CreatedAt     time.Time
	UpdatedAt     time.Time
}

// ComponentDeployStatus holds deployment status for a component.
type ComponentDeployStatus struct {
	ComponentPath string           // e.g., "services/auth-api"
	ComponentName string           // e.g., "auth-api"
	ComponentType string           // e.g., "service", "worker", "app"
	Image         string           // Container image
	Replicas      int              // Desired replicas
	ReadyReplicas int              // Ready replicas
	URL           string           // URL if component has ingress
	Status        DeploymentStatus // Current status
}

// ProjectDeployStatus holds overall deployment status for a project.
type ProjectDeployStatus struct {
	ProjectName string                  // Project identifier
	Components  []ComponentDeployStatus // Status of each deployed component
	OverallURL  string                  // Primary URL (usually app or main service)
}

// DeploymentStatus represents the state of a deployment.
type DeploymentStatus string

const (
	DeploymentStatusNone     DeploymentStatus = "none"     // No deployment exists
	DeploymentStatusPending  DeploymentStatus = "pending"  // Deployment created, waiting for pods
	DeploymentStatusRunning  DeploymentStatus = "running"  // All pods are ready
	DeploymentStatusFailed   DeploymentStatus = "failed"   // Pods failed to start
	DeploymentStatusUpdating DeploymentStatus = "updating" // Rolling update in progress
	DeploymentStatusUnknown  DeploymentStatus = "unknown"  // Status could not be determined
)

// IsReady returns true if the deployment is fully available.
func (s DeploymentStatus) IsReady() bool {
	return s == DeploymentStatusRunning
}
