// backend/internal/usermap.go
package internal

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v3"
)

// StringOrList allows a single string or a list of strings in YAML.
type StringOrList []string

func (s *StringOrList) UnmarshalYAML(value *yaml.Node) error {
	switch value.Kind {
	case yaml.ScalarNode:
		var str string
		if err := value.Decode(&str); err != nil {
			return err
		}
		*s = StringOrList{str}
		return nil
	case yaml.SequenceNode:
		var list []string
		if err := value.Decode(&list); err != nil {
			return err
		}
		*s = StringOrList(list)
		return nil
	default:
		return fmt.Errorf("expected string or list, got kind=%v", value.Kind)
	}
}

// UserMap maps a Jellyfin username to one or more relative media roots.
type UserMap struct {
	Map map[string]StringOrList `yaml:"map"`
}

// LoadUserMap loads the YAML mapping file used to resolve Jellyfin users to media roots.
func LoadUserMap(path string) (*UserMap, error) {
	b, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var m UserMap
	if err := yaml.Unmarshal(b, &m); err != nil {
		return nil, err
	}
	return &m, nil
}

// Resolve returns the first configured library for the user (back-compat).
func (m *UserMap) Resolve(username string) (string, error) {
	roots, err := m.ResolveAll(username)
	if err != nil {
		return "", err
	}
	return roots[0], nil
}

// ResolveAll returns all configured libraries for the user.
func (m *UserMap) ResolveAll(username string) ([]string, error) {
	v, ok := m.Map[username]
	if !ok || len(v) == 0 {
		return nil, fmt.Errorf("no mapping for user %q", username)
	}
	out := make([]string, 0, len(v))
	for _, dir := range v {
		dir = strings.TrimSpace(dir)
		if dir == "" {
			continue
		}
		clean := filepath.Clean(dir)
		if clean == "." || clean == "/" {
			continue
		}
		out = append(out, clean)
	}
	if len(out) == 0 {
		return nil, fmt.Errorf("no valid mapping for user %q", username)
	}
	return out, nil
}
