package config

import (
	"sort"
	"strings"
)

// Presets loads all discovered config files and returns the usable preset
// names derived from the top-level TOML sections. Raw section fragments
// like "@cloud" or "home@" are combined into invocable presets like
// "home@cloud".
func Presets() []string {
	files := DiscoverFiles()
	return presetsFrom(files)
}

// presetsFrom is the testable core of Presets. It categorises top-level
// sections and generates the list of presets a user can actually invoke.
//
// The returned list is ordered: plain presets first, then prefix@suffix
// combinations, then bare suffixes. Within each group, entries are sorted
// alphabetically.
func presetsFrom(files []string) []string {
	raw, err := loadFiles(files)
	if err != nil {
		return nil
	}

	var (
		plain    []string            // no "@"  — e.g. "archive"
		prefixes []string            // ends with "@" — e.g. "home@"
		suffixes []string            // starts with "@" — e.g. "@cloud"
		full     = map[string]bool{} // both sides — e.g. "home@cloud"
	)

	for key := range raw {
		if key == "global" || key == "vars" {
			continue
		}
		// Sub-sections like "home.backup" appear as nested maps under
		// their parent; they are never top-level keys themselves after
		// TOML parsing, so this guard is just defensive.
		if strings.Contains(key, ".") {
			continue
		}

		switch {
		case strings.HasPrefix(key, "@"):
			suffixes = append(suffixes, key)
		case strings.HasSuffix(key, "@"):
			prefixes = append(prefixes, key)
		case strings.Contains(key, "@"):
			full[key] = true
		default:
			plain = append(plain, key)
		}
	}

	sort.Strings(plain)
	sort.Strings(prefixes)
	sort.Strings(suffixes)

	seen := make(map[string]bool)
	var out []string

	add := func(s string) {
		if !seen[s] {
			seen[s] = true
			out = append(out, s)
		}
	}

	// 1. Plain presets.
	for _, p := range plain {
		add(p)
	}

	// 2. Prefix × suffix combinations.
	for _, pfx := range prefixes {
		for _, sfx := range suffixes {
			add(pfx[:len(pfx)-1] + sfx) // "home@" + "@cloud" → "home@cloud"
		}
	}

	// 3. Explicit full split presets that weren't already generated.
	fullSorted := make([]string, 0, len(full))
	for k := range full {
		fullSorted = append(fullSorted, k)
	}
	sort.Strings(fullSorted)
	for _, f := range fullSorted {
		add(f)
	}

	// 4. Bare suffixes (usable with just global defaults).
	for _, sfx := range suffixes {
		add(sfx)
	}

	return out
}

// Prefixes returns the distinct prefix fragments (sections ending with "@")
// found in the config. These are suitable for tab-completion of the first
// positional argument.
func Prefixes() []string {
	files := DiscoverFiles()
	return prefixesFrom(files)
}

func prefixesFrom(files []string) []string {
	raw, err := loadFiles(files)
	if err != nil {
		return nil
	}

	var out []string
	for key := range raw {
		if strings.HasSuffix(key, "@") {
			out = append(out, key)
		}
	}
	sort.Strings(out)
	return out
}

// Suffixes returns the distinct suffix fragments (sections starting with "@")
// found in the config. These are suitable for completing the part after "@"
// when the user has typed a prefix.
func Suffixes() []string {
	files := DiscoverFiles()
	return suffixesFrom(files)
}

func suffixesFrom(files []string) []string {
	raw, err := loadFiles(files)
	if err != nil {
		return nil
	}

	var out []string
	for key := range raw {
		if strings.HasPrefix(key, "@") {
			out = append(out, key)
		}
	}
	sort.Strings(out)
	return out
}
