package config

import (
	"os"
	"path/filepath"

	"gopkg.in/yaml.v3"
)

// Config holds the arca configuration.
type Config struct {
	Devices map[string]DeviceConfig `yaml:"devices"`
}

// DeviceConfig holds per-device settings.
type DeviceConfig struct {
	UUID       string   `yaml:"uuid"`
	Mountpoint string   `yaml:"mountpoint,omitempty"`
	Methods    []string `yaml:"methods,omitempty"`
	Keyfile    string   `yaml:"keyfile,omitempty"`
}

// ResolvedDevice holds the effective settings for a device lookup.
type ResolvedDevice struct {
	UUID       string
	Mountpoint string
	Methods    []string
	Keyfile    string
}

// Load reads the config file. Returns an empty config if the file doesn't exist.
func Load() *Config {
	cfg := &Config{
		Devices: make(map[string]DeviceConfig),
	}

	data, err := os.ReadFile(configPath())
	if err != nil {
		return cfg
	}

	yaml.Unmarshal(data, cfg)
	return cfg
}

// ResolveDevice looks up by alias name first, then checks if the argument
// is a device path matching a known alias (e.g. "/dev/sda1" matches "sda1").
// If nothing matches, returns defaults for a bare device path.
func (c *Config) ResolveDevice(nameOrPath string) ResolvedDevice {
	// Direct alias match.
	if dev, ok := c.Devices[nameOrPath]; ok {
		return resolvedFrom(dev)
	}

	// Match device path against aliases: "/dev/sda1" matches alias "sda1".
	base := filepath.Base(nameOrPath)
	if dev, ok := c.Devices[base]; ok {
		return resolvedFrom(dev)
	}

	return ResolvedDevice{
		Methods: []string{"passphrase"},
	}
}

func resolvedFrom(dev DeviceConfig) ResolvedDevice {
	methods := dev.Methods
	if len(methods) == 0 {
		methods = []string{"passphrase"}
	}
	return ResolvedDevice{
		UUID:       dev.UUID,
		Mountpoint: dev.Mountpoint,
		Methods:    methods,
		Keyfile:    dev.Keyfile,
	}
}

// AliasFor returns the config alias for a given UUID, or "" if none.
func (c *Config) AliasFor(uuid string) string {
	for name, dev := range c.Devices {
		if dev.UUID == uuid {
			return name
		}
	}
	return ""
}

// Path returns the config file path, respecting XDG_CONFIG_HOME.
func Path() string {
	return configPath()
}

func configPath() string {
	if dir := os.Getenv("XDG_CONFIG_HOME"); dir != "" {
		return filepath.Join(dir, "arca", "config.yaml")
	}
	home, _ := os.UserHomeDir()
	return filepath.Join(home, ".config", "arca", "config.yaml")
}
