package config

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

const presetsFixtureTOML = `
[global]
verbose = true

[global.backup]
exclude-file = "/etc/excludes"

[home]
repo = "/repos/home"

[home.backup]
_arguments = ["/home/alice"]

["@cloud"]
repo = "/repos/cloud"

["@cloud".environ]
AWS_PROFILE = "restic"

["home@"]
host = "laptop"

["home@cloud"]
repo = "/repos/home-cloud"

[archive]
json = true

[vars]
cache-root = "/srv"
`

func TestPresetsFrom(t *testing.T) {
	t.Parallel()

	dir := t.TempDir()
	path := filepath.Join(dir, "config.toml")
	if err := os.WriteFile(path, []byte(presetsFixtureTOML), 0o600); err != nil {
		t.Fatalf("writing fixture: %v", err)
	}

	got := presetsFrom([]string{path})

	// Plain presets first, then prefix×suffix combos, then explicit full
	// presets (already covered by combo), then bare suffixes.
	want := []string{
		"archive",
		"home",
		"home@cloud", // home@ × @cloud
		"@cloud",     // bare suffix
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("presets mismatch:\n  got:  %#v\n  want: %#v", got, want)
	}
}

func TestPresetsFromExplicitFullPreset(t *testing.T) {
	t.Parallel()

	// When an explicit full preset exists that can't be generated from
	// prefix×suffix, it should still appear.
	const fixture = `
[global]
verbose = true

["@cloud"]
repo = "/repos/cloud"

["special@remote"]
repo = "/repos/special-remote"
`
	dir := t.TempDir()
	path := filepath.Join(dir, "config.toml")
	if err := os.WriteFile(path, []byte(fixture), 0o600); err != nil {
		t.Fatalf("writing fixture: %v", err)
	}

	got := presetsFrom([]string{path})

	want := []string{
		"special@remote", // explicit full preset (no prefix@ exists)
		"@cloud",         // bare suffix
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("presets mismatch:\n  got:  %#v\n  want: %#v", got, want)
	}
}

func TestPresetsFromMultiplePrefixesSuffixes(t *testing.T) {
	t.Parallel()

	const fixture = `
[global]
verbose = true

["music@"]
tag = "music"

["photos@"]
tag = "photos"

["@hetzner"]
repo = "sftp:hetzner"

["@b2"]
repo = "s3:b2"
`
	dir := t.TempDir()
	path := filepath.Join(dir, "config.toml")
	if err := os.WriteFile(path, []byte(fixture), 0o600); err != nil {
		t.Fatalf("writing fixture: %v", err)
	}

	got := presetsFrom([]string{path})

	// Combos: each prefix × each suffix (prefixes sorted, suffixes sorted).
	want := []string{
		"music@b2",
		"music@hetzner",
		"photos@b2",
		"photos@hetzner",
		"@b2",
		"@hetzner",
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("presets mismatch:\n  got:  %#v\n  want: %#v", got, want)
	}
}

func TestPresetsFromEmpty(t *testing.T) {
	t.Parallel()

	dir := t.TempDir()
	path := filepath.Join(dir, "config.toml")
	if err := os.WriteFile(path, []byte("[global]\nverbose = true\n"), 0o600); err != nil {
		t.Fatalf("writing fixture: %v", err)
	}

	got := presetsFrom([]string{path})
	if len(got) != 0 {
		t.Fatalf("expected no presets, got %#v", got)
	}
}

func TestPresetsFromMissing(t *testing.T) {
	t.Parallel()

	got := presetsFrom([]string{"/nonexistent/path.toml"})
	if len(got) != 0 {
		t.Fatalf("expected nil for missing file, got %#v", got)
	}
}

func TestPrefixesFrom(t *testing.T) {
	t.Parallel()

	dir := t.TempDir()
	path := filepath.Join(dir, "config.toml")
	if err := os.WriteFile(path, []byte(presetsFixtureTOML), 0o600); err != nil {
		t.Fatalf("writing fixture: %v", err)
	}

	got := prefixesFrom([]string{path})
	want := []string{"home@"}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("prefixes mismatch:\n  got:  %#v\n  want: %#v", got, want)
	}
}

func TestSuffixesFrom(t *testing.T) {
	t.Parallel()

	dir := t.TempDir()
	path := filepath.Join(dir, "config.toml")
	if err := os.WriteFile(path, []byte(presetsFixtureTOML), 0o600); err != nil {
		t.Fatalf("writing fixture: %v", err)
	}

	got := suffixesFrom([]string{path})
	want := []string{"@cloud"}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("suffixes mismatch:\n  got:  %#v\n  want: %#v", got, want)
	}
}
