package cloud

import (
	"context"
	"time"
)

// InstanceSize represents the size configuration for a VM instance
type InstanceSize struct {
	ID       string  `json:"id"`
	Name     string  `json:"name"`
	CPUCores int     `json:"cpu_cores"`
	MemoryGB int     `json:"memory_gb"`
	DiskGB   int     `json:"disk_gb"`
	Price    float64 `json:"price"` // Hourly price
}

// Region represents a geographic region
type Region struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	Zone string `json:"zone"`
}

// Instance represents a virtual machine instance
type Instance struct {
	ID             string            `json:"id"`
	Name           string            `json:"name"`
	Region         string            `json:"region"`
	Size           string            `json:"size"`
	ImageID        string            `json:"image_id"`
	IPAddress      string            `json:"ip_address"`
	PrivateIP      string            `json:"private_ip,omitempty"`
	Status         string            `json:"status"` // Creating, Running, Stopping, Stopped, Restarting, Terminated
	CreatedAt      time.Time         `json:"created_at"`
	Tags           map[string]string `json:"tags,omitempty"`
	SecurityGroups []string          `json:"security_groups,omitempty"`
}

// InstanceCreateOpts are options to configure a new instance
type InstanceCreateOpts struct {
	Name           string            `json:"name"`
	Region         string            `json:"region"`
	Size           string            `json:"size"`
	ImageID        string            `json:"image_id"`
	SSHKeyIDs      []string          `json:"ssh_key_ids,omitempty"`
	UserData       string            `json:"user_data,omitempty"`
	Tags           map[string]string `json:"tags,omitempty"`
	SecurityGroups []string          `json:"security_groups,omitempty"`
}

// SSHKey represents an SSH key
type SSHKey struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	Fingerprint string    `json:"fingerprint"`
	PublicKey   string    `json:"public_key"`
	CreatedAt   time.Time `json:"created_at"`
}

// Image represents an operating system image
type Image struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	Description string    `json:"description"`
	Type        string    `json:"type"` // base, snapshot, backup
	Status      string    `json:"status"`
	CreatedAt   time.Time `json:"created_at"`
	MinDiskGB   int       `json:"min_disk_gb,omitempty"`
	SizeGB      int       `json:"size_gb,omitempty"`
}

// Provider defines the interface that all cloud providers must implement
type Provider interface {
	// Initialize sets up the provider with credentials and configuration
	Initialize(config map[string]string) error

	// Validate checks if the provider credentials are valid
	Validate(ctx context.Context) (bool, error)

	// ListRegions lists all available regions
	ListRegions(ctx context.Context) ([]Region, error)

	// ListInstanceSizes lists available VM sizes
	ListInstanceSizes(ctx context.Context, region string) ([]InstanceSize, error)

	// ListInstances lists all instances
	ListInstances(ctx context.Context) ([]Instance, error)

	// GetInstance gets a specific instance by ID
	GetInstance(ctx context.Context, id string) (*Instance, error)

	// CreateInstance creates a new instance
	CreateInstance(ctx context.Context, opts InstanceCreateOpts) (*Instance, error)

	// DeleteInstance deletes an instance
	DeleteInstance(ctx context.Context, id string) error

	// StartInstance starts an instance
	StartInstance(ctx context.Context, id string) error

	// StopInstance stops an instance
	StopInstance(ctx context.Context, id string) error

	// RestartInstance restarts an instance
	RestartInstance(ctx context.Context, id string) error

	// ListImages lists available OS images
	ListImages(ctx context.Context) ([]Image, error)

	// ListSSHKeys lists SSH keys
	ListSSHKeys(ctx context.Context) ([]SSHKey, error)

	// CreateSSHKey creates a new SSH key
	CreateSSHKey(ctx context.Context, name, publicKey string) (*SSHKey, error)

	// DeleteSSHKey deletes an SSH key
	DeleteSSHKey(ctx context.Context, id string) error

	// GetInstanceStatus gets the current status of an instance
	GetInstanceStatus(ctx context.Context, id string) (string, error)

	// WaitForInstanceStatus waits for an instance to reach a specific status
	WaitForInstanceStatus(ctx context.Context, id, status string, timeout time.Duration) error
}

// ProviderFactory is a function that creates a new provider instance
type ProviderFactory func() Provider

// providers holds a map of provider factories
var providers = make(map[string]ProviderFactory)

// RegisterProvider registers a new provider factory
func RegisterProvider(name string, factory ProviderFactory) {
	providers[name] = factory
}

// GetProvider returns a provider by name
func GetProvider(name string) (Provider, bool) {
	factory, ok := providers[name]
	if !ok {
		return nil, false
	}
	return factory(), true
}

// GetSupportedProviders returns a list of supported provider names
func GetSupportedProviders() []string {
	var names []string
	for name := range providers {
		names = append(names, name)
	}
	return names
}
