package config

import (
	"fmt"
	"os"

	"gopkg.in/yaml.v3"
)

// Config represents the DevOps CLI configuration
type Config struct {
	Project    ProjectConfig    `yaml:"project"`
	Docker     DockerConfig     `yaml:"docker"`
	Compose    ComposeConfig    `yaml:"compose"`
	Kubernetes KubernetesConfig `yaml:"kubernetes"`
	Helm       HelmConfig       `yaml:"helm"`
	Terraform  TerraformConfig  `yaml:"terraform"`
	CI         CIConfig         `yaml:"ci"`
	Cloud      CloudConfig      `yaml:"cloud"`
	Database   DatabaseConfig   `yaml:"database"`
	Monitoring MonitoringConfig `yaml:"monitoring"`
}

// ProjectConfig holds project information
type ProjectConfig struct {
	Name    string `yaml:"name"`
	Version string `yaml:"version"`
}

// DockerConfig holds Docker configuration
type DockerConfig struct {
	Context    string            `yaml:"context"`
	Dockerfile string            `yaml:"dockerfile"`
	Image      string            `yaml:"image"`
	Tag        string            `yaml:"tag"`
	Registry   string            `yaml:"registry"`
	BuildArgs  map[string]string `yaml:"build_args"`
	Labels     map[string]string `yaml:"labels"`
}

// ComposeConfig holds Docker Compose configuration
type ComposeConfig struct {
	File         string   `yaml:"file"`
	Services     []string `yaml:"services"`
	Profile      string   `yaml:"profile"`
	EnvFile      string   `yaml:"env_file"`
	RemoveOrphans bool     `yaml:"remove_orphans"`
}

// KubernetesConfig holds Kubernetes configuration
type KubernetesConfig struct {
	Context    string `yaml:"context"`
	Namespace  string `yaml:"namespace"`
	Kubeconfig string `yaml:"kubeconfig"`
	Manifests  []string `yaml:"manifests"`
}

// HelmConfig holds Helm configuration
type HelmConfig struct {
	Chart       string `yaml:"chart"`
	Release     string `yaml:"release"`
	Values      string `yaml:"values"`
	SetValues   map[string]string `yaml:"set_values"`
	Namespace   string `yaml:"namespace"`
	Timeout     string `yaml:"timeout"`
	Wait        bool   `yaml:"wait"`
	Atomic      bool   `yaml:"atomic"`
}

// TerraformConfig holds Terraform configuration
type TerraformConfig struct {
	Backend    string            `yaml:"backend"`
	State      string            `yaml:"state"`
	Vars       map[string]string `yaml:"vars"`
	VarsFiles  []string          `yaml:"vars_files"`
}

// CIConfig holds CI/CD configuration
type CIConfig struct {
	Provider  string   `yaml:"provider"`
	Workflow  string   `yaml:"workflow"`
	Variables map[string]string `yaml:"variables"`
}

// CloudConfig holds cloud provider configuration
type CloudConfig struct {
	Provider string `yaml:"provider"`
	Region   string `yaml:"region"`
	Project  string `yaml:"project"`
}

// DatabaseConfig holds database configuration
type DatabaseConfig struct {
	Type     string `yaml:"type"`
	Host     string `yaml:"host"`
	Port     int    `yaml:"port"`
	Database string `yaml:"database"`
	Username string `yaml:"username"`
	Password string `yaml:"password"`
}

// MonitoringConfig holds monitoring configuration
type MonitoringConfig struct {
	Enabled   bool   `yaml:"enabled"`
	Prometheus string `yaml:"prometheus"`
	Grafana   string `yaml:"grafana"`
}

// Default returns a default configuration
func Default() *Config {
	return &Config{
		Project: ProjectConfig{
			Name:    "myapp",
			Version: "1.0.0",
		},
		Docker: DockerConfig{
			Context:    ".",
			Dockerfile: "Dockerfile",
			Image:      "myapp",
			Tag:        "latest",
		},
		Compose: ComposeConfig{
			File: "docker-compose.yml",
		},
		Kubernetes: KubernetesConfig{
			Context:   "minikube",
			Namespace: "default",
		},
		Helm: HelmConfig{
			Timeout: "5m",
			Wait:    true,
		},
		Terraform: TerraformConfig{
			Backend: "local",
		},
		CI: CIConfig{
			Provider: "github",
		},
		Cloud: CloudConfig{
			Provider: "aws",
			Region:   "us-west-2",
		},
		Database: DatabaseConfig{
			Type: "postgres",
			Port: 5432,
		},
		Monitoring: MonitoringConfig{
			Enabled: false,
		},
	}
}

// Load loads configuration from a YAML file
func Load(path string) (*Config, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %w", err)
	}

	var cfg Config
	if err := yaml.Unmarshal(data, &cfg); err != nil {
		return nil, fmt.Errorf("failed to parse config file: %w", err)
	}

	return &cfg, nil
}

// Save saves configuration to a YAML file
func (c *Config) Save(path string) error {
	data, err := yaml.Marshal(c)
	if err != nil {
		return fmt.Errorf("failed to marshal config: %w", err)
	}

	if err := os.WriteFile(path, data, 0644); err != nil {
		return fmt.Errorf("failed to write config file: %w", err)
	}

	return nil
}

// Validate validates the configuration
func (c *Config) Validate() error {
	if c.Project.Name == "" {
		return fmt.Errorf("project name is required")
	}

	if c.Docker.Image == "" {
		return fmt.Errorf("docker image is required")
	}

	return nil
}

// Merge merges another config into this one
func (c *Config) Merge(other *Config) *Config {
	result := *c

	if other.Project.Name != "" {
		result.Project.Name = other.Project.Name
	}
	if other.Project.Version != "" {
		result.Project.Version = other.Project.Version
	}
	if other.Docker.Image != "" {
		result.Docker.Image = other.Docker.Image
	}
	if other.Docker.Context != "" {
		result.Docker.Context = other.Docker.Context
	}
	if other.Docker.Dockerfile != "" {
		result.Docker.Dockerfile = other.Docker.Dockerfile
	}
	if other.Kubernetes.Namespace != "" {
		result.Kubernetes.Namespace = other.Kubernetes.Namespace
	}
	if other.Helm.Chart != "" {
		result.Helm.Chart = other.Helm.Chart
	}
	if other.Helm.Release != "" {
		result.Helm.Release = other.Helm.Release
	}
	if other.Cloud.Provider != "" {
		result.Cloud.Provider = other.Cloud.Provider
	}
	if other.Cloud.Region != "" {
		result.Cloud.Region = other.Cloud.Region
	}

	return &result
}

// GetFullImageName returns the full image name with registry
func (c *Config) GetFullImageName() string {
	image := c.Docker.Image
	if c.Docker.Tag != "" {
		image = fmt.Sprintf("%s:%s", image, c.Docker.Tag)
	}
	if c.Docker.Registry != "" {
		image = fmt.Sprintf("%s/%s", c.Docker.Registry, image)
	}
	return image
}
