package internal

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

	"gopkg.in/yaml.v3"
)

func TestStringOrListUnmarshalScalarAndList(t *testing.T) {
	var scalar struct {
		Map map[string]StringOrList `yaml:"map"`
	}
	if err := yaml.Unmarshal([]byte("map:\n  alice: photos\n"), &scalar); err != nil {
		t.Fatalf("scalar unmarshal failed: %v", err)
	}
	if got, want := []string(scalar.Map["alice"]), []string{"photos"}; !reflect.DeepEqual(got, want) {
		t.Fatalf("scalar mismatch got=%v want=%v", got, want)
	}

	var list struct {
		Map map[string]StringOrList `yaml:"map"`
	}
	if err := yaml.Unmarshal([]byte("map:\n  brad: [movies, shows]\n"), &list); err != nil {
		t.Fatalf("list unmarshal failed: %v", err)
	}
	if got, want := []string(list.Map["brad"]), []string{"movies", "shows"}; !reflect.DeepEqual(got, want) {
		t.Fatalf("list mismatch got=%v want=%v", got, want)
	}
}

func TestStringOrListUnmarshalInvalidKind(t *testing.T) {
	var data struct {
		Map map[string]StringOrList `yaml:"map"`
	}
	err := yaml.Unmarshal([]byte("map:\n  nope:\n    nested: bad\n"), &data)
	if err == nil {
		t.Fatalf("expected unmarshal error for mapping node")
	}
}

func TestLoadUserMapAndResolve(t *testing.T) {
	tempDir := t.TempDir()
	mapPath := filepath.Join(tempDir, "user-map.yaml")
	content := "map:\n  alice: media/photos\n  brad: [movies, ' clips ', '', '/', '.']\n"
	if err := os.WriteFile(mapPath, []byte(content), 0o644); err != nil {
		t.Fatalf("write user map failed: %v", err)
	}

	m, err := LoadUserMap(mapPath)
	if err != nil {
		t.Fatalf("LoadUserMap failed: %v", err)
	}

	root, err := m.Resolve("alice")
	if err != nil {
		t.Fatalf("Resolve failed: %v", err)
	}
	if root != filepath.Clean("media/photos") {
		t.Fatalf("unexpected resolved root %q", root)
	}

	roots, err := m.ResolveAll("brad")
	if err != nil {
		t.Fatalf("ResolveAll failed: %v", err)
	}
	if got, want := roots, []string{"movies", "clips"}; !reflect.DeepEqual(got, want) {
		t.Fatalf("ResolveAll mismatch got=%v want=%v", got, want)
	}
}

func TestLoadUserMapMissingFile(t *testing.T) {
	_, err := LoadUserMap("/definitely/missing/user-map.yaml")
	if err == nil {
		t.Fatalf("expected error for missing file")
	}
}

func TestResolveAllMissingAndInvalidEntries(t *testing.T) {
	m := &UserMap{Map: map[string]StringOrList{
		"empty": {"", " ", "/", "."},
	}}

	if _, err := m.ResolveAll("unknown"); err == nil {
		t.Fatalf("expected missing-user error")
	}
	if _, err := m.ResolveAll("empty"); err == nil {
		t.Fatalf("expected invalid-mapping error")
	}
}

func TestResolveReturnsFirstMappingAndMissingUser(t *testing.T) {
	m := &UserMap{Map: map[string]StringOrList{"brad": {"first", "second"}}}
	got, err := m.Resolve("brad")
	if err != nil {
		t.Fatalf("Resolve failed: %v", err)
	}
	if got != "first" {
		t.Fatalf("expected first mapping, got %q", got)
	}
	if _, err := m.Resolve("missing"); err == nil {
		t.Fatalf("expected missing-user error")
	}
}
