package browser

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

func TestListChromeProfiles(t *testing.T) {
	// Build a temporary user-data-dir that mimics a real Chrome layout.
	tmpDir := t.TempDir()

	// --- Local State with info_cache ---
	localStateData := map[string]any{
		"profile": map[string]any{
			"info_cache": map[string]any{
				"Default":   map[string]any{"name": "Main Account"},
				"Profile 1": map[string]any{"name": "Work"},
			},
		},
	}
	lsBytes, _ := json.Marshal(localStateData)
	if err := os.WriteFile(filepath.Join(tmpDir, "Local State"), lsBytes, 0o600); err != nil {
		t.Fatal(err)
	}

	// --- Default profile: Preferences + 2 extensions ---
	defaultDir := filepath.Join(tmpDir, "Default")
	os.MkdirAll(filepath.Join(defaultDir, "Extensions", "extAAA"), 0o755)
	os.MkdirAll(filepath.Join(defaultDir, "Extensions", "extBBB"), 0o755)
	os.MkdirAll(filepath.Join(defaultDir, "Extensions", "Temp"), 0o755) // must be excluded
	os.WriteFile(filepath.Join(defaultDir, "Preferences"), []byte("{}"), 0o600)

	// --- Profile 1: Preferences + 0 extensions ---
	prof1Dir := filepath.Join(tmpDir, "Profile 1")
	os.MkdirAll(prof1Dir, 0o755)
	os.WriteFile(filepath.Join(prof1Dir, "Preferences"), []byte("{}"), 0o600)

	// --- System Profile: must be excluded ---
	sysDir := filepath.Join(tmpDir, "System Profile")
	os.MkdirAll(sysDir, 0o755)
	os.WriteFile(filepath.Join(sysDir, "Preferences"), []byte("{}"), 0o600)

	// --- Random dir without Preferences: must be excluded ---
	os.MkdirAll(filepath.Join(tmpDir, "Crashpad"), 0o755)

	t.Run("detecta perfiles con Preferences", func(t *testing.T) {
		profiles, err := ListChromeProfiles(tmpDir)
		if err != nil {
			t.Fatalf("error inesperado: %v", err)
		}
		if len(profiles) != 2 {
			t.Fatalf("esperaba 2 perfiles, got %d", len(profiles))
		}
	})

	t.Run("ordena por Dir", func(t *testing.T) {
		profiles, _ := ListChromeProfiles(tmpDir)
		if profiles[0].Dir != "Default" || profiles[1].Dir != "Profile 1" {
			t.Errorf("orden incorrecto: %v", profiles)
		}
	})

	t.Run("resuelve nombres desde Local State", func(t *testing.T) {
		profiles, _ := ListChromeProfiles(tmpDir)
		if profiles[0].Name != "Main Account" {
			t.Errorf("Default: Name = %q, want %q", profiles[0].Name, "Main Account")
		}
		if profiles[1].Name != "Work" {
			t.Errorf("Profile 1: Name = %q, want %q", profiles[1].Name, "Work")
		}
	})

	t.Run("cuenta extensiones excluyendo Temp", func(t *testing.T) {
		profiles, _ := ListChromeProfiles(tmpDir)
		if profiles[0].Extensions != 2 {
			t.Errorf("Default: Extensions = %d, want 2", profiles[0].Extensions)
		}
		if profiles[1].Extensions != 0 {
			t.Errorf("Profile 1: Extensions = %d, want 0", profiles[1].Extensions)
		}
	})

	t.Run("excluye System Profile", func(t *testing.T) {
		profiles, _ := ListChromeProfiles(tmpDir)
		for _, p := range profiles {
			if p.Dir == "System Profile" {
				t.Error("System Profile no debe aparecer en la lista")
			}
		}
	})

	t.Run("HasPreferences es true para todos los perfiles devueltos", func(t *testing.T) {
		profiles, _ := ListChromeProfiles(tmpDir)
		for _, p := range profiles {
			if !p.HasPreferences {
				t.Errorf("perfil %q: HasPreferences debe ser true", p.Dir)
			}
		}
	})

	t.Run("directorio sin Preferences no aparece", func(t *testing.T) {
		profiles, _ := ListChromeProfiles(tmpDir)
		for _, p := range profiles {
			if p.Dir == "Crashpad" {
				t.Error("Crashpad no tiene Preferences y no debe aparecer")
			}
		}
	})

	t.Run("fallback Name igual a Dir cuando no hay Local State", func(t *testing.T) {
		tmp2 := t.TempDir()
		p2 := filepath.Join(tmp2, "Profile 2")
		os.MkdirAll(p2, 0o755)
		os.WriteFile(filepath.Join(p2, "Preferences"), []byte("{}"), 0o600)

		profiles, err := ListChromeProfiles(tmp2)
		if err != nil {
			t.Fatalf("error inesperado: %v", err)
		}
		if len(profiles) != 1 {
			t.Fatalf("esperaba 1 perfil, got %d", len(profiles))
		}
		if profiles[0].Name != "Profile 2" {
			t.Errorf("Name = %q, want %q", profiles[0].Name, "Profile 2")
		}
	})

	t.Run("error si userDataDir no existe", func(t *testing.T) {
		_, err := ListChromeProfiles("/tmp/nonexistent_chrome_dir_99999")
		if err == nil {
			t.Error("esperaba error para directorio inexistente")
		}
	})
}
