package infra

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

func TestVaultManifestRead_HappyPath(t *testing.T) {
	root := t.TempDir()

	writeManifest(t, root, "app_turismo", `
vaults:
  - name: turismo_spain
    description: "Datos de turismo en Espana"
    path: "/home/lucas/vaults/turismo_spain"
    tags: [turismo, espana]
  - name: turismo_raw
    description: "Datos brutos sin procesar"
    path: "/home/lucas/vaults/turismo_raw"
    tags: [raw]
`)

	writeManifest(t, root, "app_finance", `
vaults:
  - name: finance_data
    description: "Datos financieros"
    path: "/home/lucas/vaults/finance_data"
    tags: [finance]
`)

	entries, err := VaultManifestRead(root)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if len(entries) != 3 {
		t.Fatalf("got %d entries, want 3", len(entries))
	}

	// Build index by name for order-independent assertions.
	byName := make(map[string]VaultManifestEntry, len(entries))
	for _, e := range entries {
		byName[e.Name] = e
	}

	// Check turismo_spain entry.
	e, ok := byName["turismo_spain"]
	if !ok {
		t.Fatal("missing entry 'turismo_spain'")
	}
	if e.ProjectID != "app_turismo" {
		t.Errorf("turismo_spain.ProjectID = %q, want %q", e.ProjectID, "app_turismo")
	}
	if e.Path != "/home/lucas/vaults/turismo_spain" {
		t.Errorf("turismo_spain.Path = %q, want %q", e.Path, "/home/lucas/vaults/turismo_spain")
	}
	if len(e.Tags) != 2 || e.Tags[0] != "turismo" {
		t.Errorf("turismo_spain.Tags = %v, want [turismo espana]", e.Tags)
	}
	if e.ManifestFile == "" {
		t.Error("turismo_spain.ManifestFile is empty")
	}

	// Check finance_data entry belongs to app_finance.
	ef, ok := byName["finance_data"]
	if !ok {
		t.Fatal("missing entry 'finance_data'")
	}
	if ef.ProjectID != "app_finance" {
		t.Errorf("finance_data.ProjectID = %q, want %q", ef.ProjectID, "app_finance")
	}
}

func TestVaultManifestRead_MalformedYAML(t *testing.T) {
	root := t.TempDir()

	writeManifest(t, root, "bad_project", `
vaults:
  - name: [invalid yaml
    path: missing_bracket
`)

	_, err := VaultManifestRead(root)
	if err == nil {
		t.Fatal("expected error for malformed YAML, got nil")
	}
}

func TestVaultManifestRead_EmptyDir(t *testing.T) {
	root := t.TempDir()

	// No projects/ directory at all — glob returns no matches.
	entries, err := VaultManifestRead(root)
	if err != nil {
		t.Fatalf("unexpected error for empty dir: %v", err)
	}
	if len(entries) != 0 {
		t.Fatalf("got %d entries, want 0", len(entries))
	}
}

// writeManifest creates <root>/projects/<proj>/vaults/vault.yaml with the given content.
func writeManifest(t *testing.T, root, proj, content string) {
	t.Helper()
	dir := filepath.Join(root, "projects", proj, "vaults")
	if err := os.MkdirAll(dir, 0o755); err != nil {
		t.Fatalf("mkdir %s: %v", dir, err)
	}
	f := filepath.Join(dir, "vault.yaml")
	if err := os.WriteFile(f, []byte(content), 0o644); err != nil {
		t.Fatalf("write %s: %v", f, err)
	}
}
