package suggest

import (
	"strings"
	"testing"
)

func TestFindSimilar(t *testing.T) {
	tests := []struct {
		name       string
		target     string
		candidates []string
		maxResults int
		wantFirst  string // expect this to be the first result
	}{
		{
			name:       "exact prefix match",
			target:     "toa",
			candidates: []string{"Toast", "Nux", "Capable", "Ghost"},
			maxResults: 3,
			wantFirst:  "Toast",
		},
		{
			name:       "typo match",
			target:     "Tosat",
			candidates: []string{"Toast", "Nux", "Capable"},
			maxResults: 3,
			wantFirst:  "Toast",
		},
		{
			name:       "case insensitive",
			target:     "TOAST",
			candidates: []string{"Nux", "Toast", "Capable"},
			maxResults: 1,
			wantFirst:  "Toast", // finds Toast even with different case
		},
		{
			name:       "no matches",
			target:     "xyz",
			candidates: []string{"abc", "def"},
			maxResults: 3,
			wantFirst:  "", // no good matches
		},
		{
			name:       "empty candidates",
			target:     "test",
			candidates: []string{},
			maxResults: 3,
			wantFirst:  "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			results := FindSimilar(tt.target, tt.candidates, tt.maxResults)

			if tt.wantFirst == "" {
				if len(results) > 0 {
					// Allow some results for partial matches, just check they're reasonable
					return
				}
				return
			}

			if len(results) == 0 {
				t.Errorf("FindSimilar(%q) returned no results, want first = %q", tt.target, tt.wantFirst)
				return
			}

			if results[0] != tt.wantFirst {
				t.Errorf("FindSimilar(%q) first result = %q, want %q", tt.target, results[0], tt.wantFirst)
			}
		})
	}
}

func TestLevenshteinDistance(t *testing.T) {
	tests := []struct {
		a, b string
		want int
	}{
		{"", "", 0},
		{"a", "", 1},
		{"", "a", 1},
		{"abc", "abc", 0},
		{"abc", "abd", 1},
		{"abc", "adc", 1},
		{"abc", "abcd", 1},
		{"kitten", "sitting", 3},
	}

	for _, tt := range tests {
		t.Run(tt.a+"_"+tt.b, func(t *testing.T) {
			got := levenshteinDistance(tt.a, tt.b)
			if got != tt.want {
				t.Errorf("levenshteinDistance(%q, %q) = %d, want %d", tt.a, tt.b, got, tt.want)
			}
		})
	}
}

func TestFormatSuggestion(t *testing.T) {
	msg := FormatSuggestion("Polecat", "Tosat", []string{"Toast", "Ghost"}, "Create with: gt polecat add Tosat")

	if !strings.Contains(msg, "Polecat") {
		t.Errorf("FormatSuggestion missing entity name")
	}
	if !strings.Contains(msg, "Tosat") {
		t.Errorf("FormatSuggestion missing target name")
	}
	if !strings.Contains(msg, "Did you mean?") {
		t.Errorf("FormatSuggestion missing 'Did you mean?' section")
	}
	if !strings.Contains(msg, "Toast") {
		t.Errorf("FormatSuggestion missing suggestion 'Toast'")
	}
	if !strings.Contains(msg, "Create with:") {
		t.Errorf("FormatSuggestion missing hint")
	}
}
