// ABOUTME: Core types for EdgeConnect deployment planning and execution
// ABOUTME: Defines data structures for deployment plans, actions, and results
package apply

import (
	"fmt"
	"strings"
	"time"

	"edp.buildth.ing/DevFW-CICD/edge-connect-client/internal/config"
	"edp.buildth.ing/DevFW-CICD/edge-connect-client/internal/core/domain"
)

// ActionType defines the type of action to be performed
type ActionType string

const (
	ActionNone   ActionType = "NONE"
	ActionCreate ActionType = "CREATE"
	ActionUpdate ActionType = "UPDATE"
	ActionDelete ActionType = "DELETE"
)

// AppType defines the type of application deployment
type AppType string

const (
	AppTypeK8s    AppType = "KUBERNETES"
	AppTypeDocker AppType = "DOCKER"
)

// AppState represents the desired or current state of an application
type AppState struct {
	Name                    string
	Version                 string
	Organization            string
	Region                  string
	AppType                 AppType
	ManifestHash            string
	OutboundConnections     []domain.SecurityRule
	Exists                  bool
	LastUpdated             time.Time
}

// InstanceState represents the desired or current state of an application instance
type InstanceState struct {
	Name         string
	AppName      string
	AppVersion   string
	Organization string
	Region       string
	CloudletOrg  string
	CloudletName string
	FlavorName   string
	State        string
	PowerState   string
	Exists       bool
	LastUpdated  time.Time
}

// AppAction defines an action to be performed on an application
type AppAction struct {
	Type            ActionType
	Desired         *AppState
	Current         *AppState
	ManifestHash    string
	ManifestChanged bool
	Reason          string
	Changes         []string
}

// InstanceAction defines an action to be performed on an application instance
type InstanceAction struct {
	Type         ActionType
	Target       config.InfraTemplate
	Desired      *InstanceState
	Current      *InstanceState
	InstanceName string
	Reason       string
	Changes      []string
}

// DeploymentPlan represents a plan of actions to achieve the desired state
type DeploymentPlan struct {
	ConfigName      string
	CreatedAt       time.Time
	DryRun          bool
	AppAction       AppAction
	InstanceActions []InstanceAction
	TotalActions    int
	EstimatedDuration time.Duration
	Summary         string
}

// IsEmpty returns true if the plan contains no actions
func (p *DeploymentPlan) IsEmpty() bool {
	return p.AppAction.Type == ActionNone && len(p.InstanceActions) == 0
}

// Validate checks the validity of the deployment plan
func (p *DeploymentPlan) Validate() error {
	if p.AppAction.Type == ActionNone && len(p.InstanceActions) == 0 {
		return fmt.Errorf("deployment plan is empty")
	}
	// Add more validation rules as needed
	return nil
}

// GenerateSummary creates a human-readable summary of the plan
func (p *DeploymentPlan) GenerateSummary() string {
	var sb strings.Builder
	sb.WriteString(fmt.Sprintf("Plan for '%s' (created: %s, dry-run: %t)\n", p.ConfigName, p.CreatedAt.Format(time.RFC3339), p.DryRun))
	sb.WriteString("--------------------------------------------------\n")

	if p.AppAction.Type != ActionNone {
		sb.WriteString(fmt.Sprintf("Application '%s': %s - %s\n", p.AppAction.Desired.Name, p.AppAction.Type, p.AppAction.Reason))
		for _, change := range p.AppAction.Changes {
			sb.WriteString(fmt.Sprintf("  - %s\n", change))
		}
	}

	for _, action := range p.InstanceActions {
		sb.WriteString(fmt.Sprintf("Instance '%s' on '%s': %s - %s\n", action.InstanceName, action.Target.CloudletName, action.Type, action.Reason))
		for _, change := range action.Changes {
			sb.WriteString(fmt.Sprintf("  - %s\n", change))
		}
	}

	sb.WriteString("--------------------------------------------------\n")
	sb.WriteString(fmt.Sprintf("Total actions: %d, Estimated duration: %v\n", p.TotalActions, p.EstimatedDuration))
	return sb.String()
}

// PlanResult holds the result of a planning operation
type PlanResult struct {
	Plan     *DeploymentPlan
	Warnings []string
	Error    error
}

// ExecutionResult holds the result of a deployment execution
type ExecutionResult struct {
	Plan              *DeploymentPlan
	Success           bool
	Error             error
	Duration          time.Duration
	CompletedActions  []ActionResult
	FailedActions     []ActionResult
	RollbackPerformed bool
	RollbackSuccess   bool
}

// ActionResult details the outcome of a single action
type ActionResult struct {
	Type    ActionType
	Target  string
	Success bool
	Error   error
	Details string
	Duration time.Duration
}