package lsp

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

func TestDefaultLSPRegistry(t *testing.T) {
	reg := DefaultLSPRegistry()
	if reg.SchemaVersion != "v1" {
		t.Errorf("Expected v1, got %s", reg.SchemaVersion)
	}
	if len(reg.Servers) == 0 {
		t.Error("Default LSP registry should have servers")
	}

	names := map[string]bool{}
	for _, s := range reg.Servers {
		if names[s.Name] {
			t.Errorf("Duplicate server name: %s", s.Name)
		}
		names[s.Name] = true
		if s.Command == "" {
			t.Errorf("Server %s missing command", s.Name)
		}
		if s.Language == "" {
			t.Errorf("Server %s missing language", s.Name)
		}
	}
}

func TestSaveAndLoadLSPRegistry(t *testing.T) {
	tmpDir := t.TempDir()
	SetLSPRegistryPath(filepath.Join(tmpDir, "lsp-registry.yaml"))

	reg := DefaultLSPRegistry()
	if err := SaveLSPRegistry(reg); err != nil {
		t.Fatalf("SaveLSPRegistry failed: %v", err)
	}

	loaded, err := LoadLSPRegistry()
	if err != nil {
		t.Fatalf("LoadLSPRegistry failed: %v", err)
	}
	if len(loaded.Servers) != len(reg.Servers) {
		t.Errorf("Expected %d servers, got %d", len(reg.Servers), len(loaded.Servers))
	}
}

func TestInitLSPRegistry(t *testing.T) {
	tmpDir := t.TempDir()
	SetLSPRegistryPath(filepath.Join(tmpDir, "lsp-reg.yaml"))

	if err := InitLSPRegistry(); err != nil {
		t.Fatalf("InitLSPRegistry failed: %v", err)
	}

	if _, err := os.Stat(filepath.Join(tmpDir, "lsp-reg.yaml")); os.IsNotExist(err) {
		t.Error("LSP registry file should be created")
	}
}

func TestDetectProjectLanguages(t *testing.T) {
	tmpDir := t.TempDir()

	os.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte("module test\ngo 1.24\n"), 0644)
	os.WriteFile(filepath.Join(tmpDir, "package.json"), []byte(`{"name": "test"}`), 0644)

	languages := DetectProjectLanguages(tmpDir)
	if len(languages) == 0 {
		t.Error("Should detect languages")
	}

	langSet := map[string]bool{}
	for _, l := range languages {
		langSet[l] = true
	}
	if !langSet["go"] {
		t.Error("Should detect Go")
	}
	if !langSet["typescript"] {
		t.Error("Should detect TypeScript/JS from package.json")
	}
}

func TestDetectProjectLanguagesEmpty(t *testing.T) {
	tmpDir := t.TempDir()
	languages := DetectProjectLanguages(tmpDir)
	if len(languages) != 0 {
		t.Errorf("Empty dir should detect no languages, got %v", languages)
	}
}

func TestGenerateNeovimConfig(t *testing.T) {
	servers := []RegistryEntry{
		{Name: "gopls", Language: "go", NeovimSetup: "lspconfig.gopls.setup{}"},
		{Name: "pyright", Language: "python", NeovimSetup: "lspconfig.pyright.setup{}"},
	}

	config := GenerateNeovimConfig(servers)
	if config == "" {
		t.Error("Config should not be empty")
	}
	if len(config) < 50 {
		t.Error("Config seems too short")
	}
}

func TestGenerateHelixConfig(t *testing.T) {
	servers := []RegistryEntry{
		{Name: "gopls", Language: "go", HelixLanguage: "go"},
	}

	config := GenerateHelixConfig(servers)
	if config == "" {
		t.Error("Config should not be empty")
	}
}

func TestGenerateVSCodeRecommendations(t *testing.T) {
	servers := []RegistryEntry{
		{Name: "gopls", Language: "go"},
		{Name: "pyright", Language: "python"},
	}

	exts := GenerateVSCodeRecommendations(servers)
	if len(exts) == 0 {
		t.Error("Should return some extensions")
	}
}

func TestHealthCheck(t *testing.T) {
	healthy, detail := HealthCheck("gopls")
	if healthy && detail == "" {
		t.Error("If healthy, should have version detail")
	}
}

func TestHealthCheckUnknown(t *testing.T) {
	_, _ = HealthCheck("nonexistent-server")
}
