package main

import (
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func TestParseEnvFile(t *testing.T) {
	path := filepath.Join(t.TempDir(), "profile.env")
	if err := os.WriteFile(path, []byte("\n# comment\nexport RESTIC_REPOSITORY = 's3:bucket'\nRESTIC_PASSWORD=\"secret value\"\nBARE=value\ninvalid line\n"), 0600); err != nil {
		t.Fatal(err)
	}

	got, err := parseEnvFile(path)
	if err != nil {
		t.Fatal(err)
	}
	want := map[string]string{"RESTIC_REPOSITORY": "s3:bucket", "RESTIC_PASSWORD": "secret value", "BARE": "value"}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("parseEnvFile() = %#v, want %#v", got, want)
	}
}

func TestProfileRepositoryError(t *testing.T) {
	tests := []struct {
		name       string
		backend    string
		env        string
		missingEnv bool
		want       string
	}{
		{name: "valid restic environment", backend: "restic", env: "RESTIC_REPOSITORY=/repo\nRESTIC_PASSWORD=secret\n"},
		{name: "valid rustic environment", backend: "rustic", env: "RUSTIC_REPOSITORY=/repo\n"},
		{name: "missing env file", backend: "restic", missingEnv: true, want: "Env file not available"},

		{name: "missing repository", backend: "restic", env: "RESTIC_PASSWORD=secret\n", want: "RESTIC_REPOSITORY not set in env file"},
		{name: "missing restic password", backend: "restic", env: "RESTIC_REPOSITORY=/repo\n", want: "No password set in env file"},
		{name: "unsupported backend", backend: "borg", env: "BORG_REPOSITORY=/repo\n", want: "Unsupported backend: borg"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			envFile := filepath.Join(t.TempDir(), "profile.env")
			if !tt.missingEnv {
				if err := os.WriteFile(envFile, []byte(tt.env), 0600); err != nil {
					t.Fatal(err)
				}
			}
			prof := Profile{Backend: tt.backend, EnvFile: envFile}
			if got := prof.repositoryError(); got != tt.want {
				t.Fatalf("repositoryError() = %q, want %q", got, tt.want)
			}
		})
	}
}

func TestProfileScheduleError(t *testing.T) {
	enabled := true
	disabled := false
	tests := []struct {
		name   string
		backup *bool
		paths  []string
		prune  bool
		want   string
	}{
		{name: "backup enabled by default without paths", want: "No paths configured"},
		{name: "backup explicitly enabled without paths", backup: &enabled, want: "No paths configured"},
		{name: "backup enabled with paths", paths: []string{"/data"}},
		{name: "prune only without paths", backup: &disabled, prune: true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			envFile := filepath.Join(t.TempDir(), "profile.env")
			if err := os.WriteFile(envFile, []byte("RESTIC_REPOSITORY=/repo\nRESTIC_PASSWORD=secret\n"), 0600); err != nil {
				t.Fatal(err)
			}
			prof := Profile{
				Backend:  "restic",
				EnvFile:  envFile,
				Schedule: Schedule{Backup: tt.backup, Prune: tt.prune},
				Backup:   Backup{Paths: tt.paths},
			}
			if got := prof.scheduleError(); got != tt.want {
				t.Fatalf("scheduleError() = %q, want %q", got, tt.want)
			}
		})
	}
}

func TestLoadConfig(t *testing.T) {
	dir := t.TempDir()
	old := configDirOverride
	configDirOverride = dir
	t.Cleanup(func() { configDirOverride = old })

	contents := "[[profiles]]\nname = 'work'\n[profiles.backup]\npaths = ['/home/me']\n[profiles.prune]\nargs = ['--keep-last', '2']\n[profiles.check]\nargs = ['--read-data']\n[profiles.mount]\nargs = ['--allow-other']\n"
	if err := os.WriteFile(configPath(), []byte(contents), 0600); err != nil {
		t.Fatal(err)
	}
	cfg := loadConfig()
	if cfg.loadErr != nil {
		t.Fatal(cfg.loadErr)
	}
	p := cfg.Profiles[0]
	if p.Backend != "restic" || p.EnvFile != filepath.Join(dir, "work.env") || p.RetryLock != "2m" {
		t.Fatalf("unexpected profile defaults: %#v", p)
	}
	if !reflect.DeepEqual(p.Backup.Args, []string{"--exclude-caches", "--exclude", "*.tmp"}) {
		t.Fatalf("backup defaults = %#v", p.Backup.Args)
	}
	if !reflect.DeepEqual(p.Prune.Args, []string{"--keep-last", "2"}) {
		t.Fatalf("prune options = %#v", p.Prune.Args)
	}
	if !reflect.DeepEqual(p.Check.Args, []string{"--read-data"}) {
		t.Fatalf("check options = %#v", p.Check.Args)
	}
	if !reflect.DeepEqual(p.Mount.Args, []string{"--allow-other"}) {
		t.Fatalf("mount options = %#v", p.Mount.Args)
	}

	if err := os.WriteFile(configPath(), []byte("[[profiles]]\nname = 'same'\n[[profiles]]\nname = 'same'\n"), 0600); err != nil {
		t.Fatal(err)
	}
	if cfg := loadConfig(); cfg.loadErr == nil {
		t.Fatal("expected duplicate profile names to be rejected")
	}
}
