package config

import (
	"os"
	"testing"
)

func TestDefault(t *testing.T) {
	cfg := Default()

	if cfg.Project.Name != "myapp" {
		t.Errorf("Expected project name 'myapp', got '%s'", cfg.Project.Name)
	}

	if cfg.Docker.Image != "myapp" {
		t.Errorf("Expected docker image 'myapp', got '%s'", cfg.Docker.Image)
	}

	if cfg.Kubernetes.Namespace != "default" {
		t.Errorf("Expected kubernetes namespace 'default', got '%s'", cfg.Kubernetes.Namespace)
	}
}

func TestLoad(t *testing.T) {
	// Create temporary config file
	content := `
project:
  name: testapp
  version: 2.0.0
docker:
  image: testapp
  tag: v2.0.0
`
	tmpfile, err := os.CreateTemp("", "devops*.yml")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(tmpfile.Name())

	if _, err := tmpfile.Write([]byte(content)); err != nil {
		t.Fatal(err)
	}
	if err := tmpfile.Close(); err != nil {
		t.Fatal(err)
	}

	// Test loading
	cfg, err := Load(tmpfile.Name())
	if err != nil {
		t.Errorf("Failed to load config: %v", err)
	}

	if cfg.Project.Name != "testapp" {
		t.Errorf("Expected project name 'testapp', got '%s'", cfg.Project.Name)
	}

	if cfg.Docker.Tag != "v2.0.0" {
		t.Errorf("Expected docker tag 'v2.0.0', got '%s'", cfg.Docker.Tag)
	}
}

func TestSave(t *testing.T) {
	cfg := Default()
	tmpfile, err := os.CreateTemp("", "devops*.yml")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(tmpfile.Name())

	if err := cfg.Save(tmpfile.Name()); err != nil {
		t.Errorf("Failed to save config: %v", err)
	}

	// Verify saved file
	savedCfg, err := Load(tmpfile.Name())
	if err != nil {
		t.Errorf("Failed to load saved config: %v", err)
	}

	if savedCfg.Project.Name != cfg.Project.Name {
		t.Errorf("Names don't match: '%s' vs '%s'", savedCfg.Project.Name, cfg.Project.Name)
	}
}

func TestValidate(t *testing.T) {
	tests := []struct {
		name    string
		config  *Config
		wantErr bool
	}{
		{
			name:    "valid config",
			config:  &Config{Project: ProjectConfig{Name: "test"}, Docker: DockerConfig{Image: "test"}},
			wantErr: false,
		},
		{
			name:    "missing project name",
			config:  &Config{Project: ProjectConfig{Name: ""}, Docker: DockerConfig{Image: "test"}},
			wantErr: true,
		},
		{
			name:    "missing docker image",
			config:  &Config{Project: ProjectConfig{Name: "test"}, Docker: DockerConfig{Image: ""}},
			wantErr: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := tt.config.Validate()
			if (err != nil) != tt.wantErr {
				t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func TestMerge(t *testing.T) {
	base := &Config{
		Project: ProjectConfig{Name: "base", Version: "1.0.0"},
		Docker:  DockerConfig{Image: "base-image", Tag: "v1"},
	}

	override := &Config{
		Project: ProjectConfig{Name: "override", Version: "2.0.0"},
		Docker:  DockerConfig{Image: "override-image"},
		Cloud:   CloudConfig{Provider: "aws"},
	}

	result := base.Merge(override)

	if result.Project.Name != "override" {
		t.Errorf("Expected project name 'override', got '%s'", result.Project.Name)
	}

	if result.Project.Version != "2.0.0" {
		t.Errorf("Expected version '2.0.0', got '%s'", result.Project.Version)
	}

	if result.Docker.Image != "override-image" {
		t.Errorf("Expected image 'override-image', got '%s'", result.Docker.Image)
	}

	// Tag should remain from base since override didn't set it
	if result.Docker.Tag != "v1" {
		t.Errorf("Expected tag 'v1', got '%s'", result.Docker.Tag)
	}

	if result.Cloud.Provider != "aws" {
		t.Errorf("Expected provider 'aws', got '%s'", result.Cloud.Provider)
	}
}

func TestGetFullImageName(t *testing.T) {
	tests := []struct {
		name     string
		config   *Config
		expected string
	}{
		{
			name: "with registry",
			config: &Config{
				Docker: DockerConfig{
					Image:    "myapp",
					Tag:      "latest",
					Registry: "ghcr.io/user",
				},
			},
			expected: "ghcr.io/user/myapp:latest",
		},
		{
			name: "without registry",
			config: &Config{
				Docker: DockerConfig{
					Image: "myapp",
					Tag:   "v1.0.0",
				},
			},
			expected: "myapp:v1.0.0",
		},
		{
			name: "without tag",
			config: &Config{
				Docker: DockerConfig{
					Image: "myapp",
				},
			},
			expected: "myapp:latest",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := tt.config.GetFullImageName()
			if result != tt.expected {
				t.Errorf("GetFullImageName() = %v, want %v", result, tt.expected)
			}
		})
	}
}
