package models

import "testing"

func TestGetAnthropicModelAliases_StaticOnly(t *testing.T) {
	aliases := GetAnthropicModelAliases([]string{"sonnet-4.6", "opus-4.5"})
	if len(aliases) != 2 {
		t.Fatalf("expected 2 aliases, got %d: %v", len(aliases), aliases)
	}
	ids := map[string]string{}
	for _, a := range aliases {
		ids[a.ID] = a.Name
	}
	if ids["claude-sonnet-4-6"] != "Claude 4.6 Sonnet" {
		t.Errorf("unexpected name for claude-sonnet-4-6: %s", ids["claude-sonnet-4-6"])
	}
	if ids["claude-opus-4-5"] != "Claude 4.5 Opus" {
		t.Errorf("unexpected name for claude-opus-4-5: %s", ids["claude-opus-4-5"])
	}
}

func TestGetAnthropicModelAliases_DynamicFallback(t *testing.T) {
	aliases := GetAnthropicModelAliases([]string{"sonnet-4.7", "opus-5.0-thinking", "gpt-4o"})
	ids := map[string]string{}
	for _, a := range aliases {
		ids[a.ID] = a.Name
	}
	if ids["claude-sonnet-4-7"] != "Sonnet 4.7" {
		t.Errorf("unexpected name for claude-sonnet-4-7: %s", ids["claude-sonnet-4-7"])
	}
	if ids["claude-opus-5-0-thinking"] != "Opus 5.0 (Thinking)" {
		t.Errorf("unexpected name for claude-opus-5-0-thinking: %s", ids["claude-opus-5-0-thinking"])
	}
	if _, ok := ids["claude-gpt-4o"]; ok {
		t.Errorf("gpt-4o should not generate a claude alias")
	}
}

func TestGetAnthropicModelAliases_Mixed(t *testing.T) {
	aliases := GetAnthropicModelAliases([]string{"sonnet-4.6", "opus-4.7", "gpt-4o"})
	ids := map[string]string{}
	for _, a := range aliases {
		ids[a.ID] = a.Name
	}
	// static entry keeps its custom name
	if ids["claude-sonnet-4-6"] != "Claude 4.6 Sonnet" {
		t.Errorf("static alias should keep original name, got: %s", ids["claude-sonnet-4-6"])
	}
	// dynamic entry uses auto-generated name
	if ids["claude-opus-4-7"] != "Opus 4.7" {
		t.Errorf("dynamic alias name mismatch: %s", ids["claude-opus-4-7"])
	}
}

func TestGetAnthropicModelAliases_UnknownPattern(t *testing.T) {
	aliases := GetAnthropicModelAliases([]string{"some-unknown-model"})
	if len(aliases) != 0 {
		t.Fatalf("expected 0 aliases for unknown pattern, got %d: %v", len(aliases), aliases)
	}
}

func TestResolveToCursorModel_Static(t *testing.T) {
	tests := []struct {
		input string
		want  string
	}{
		{"claude-opus-4-6", "opus-4.6"},
		{"claude-opus-4.6", "opus-4.6"},
		{"claude-sonnet-4-5", "sonnet-4.5"},
		{"claude-opus-4-6-thinking", "opus-4.6-thinking"},
	}
	for _, tc := range tests {
		got := ResolveToCursorModel(tc.input)
		if got != tc.want {
			t.Errorf("ResolveToCursorModel(%q) = %q, want %q", tc.input, got, tc.want)
		}
	}
}

func TestResolveToCursorModel_DynamicFallback(t *testing.T) {
	tests := []struct {
		input string
		want  string
	}{
		{"claude-opus-4-7", "opus-4.7"},
		{"claude-sonnet-5-0", "sonnet-5.0"},
		{"claude-opus-4-7-thinking", "opus-4.7-thinking"},
		{"claude-sonnet-5-0-thinking", "sonnet-5.0-thinking"},
	}
	for _, tc := range tests {
		got := ResolveToCursorModel(tc.input)
		if got != tc.want {
			t.Errorf("ResolveToCursorModel(%q) = %q, want %q", tc.input, got, tc.want)
		}
	}
}

func TestResolveToCursorModel_Passthrough(t *testing.T) {
	tests := []string{"sonnet-4.6", "gpt-4o", "custom-model"}
	for _, input := range tests {
		got := ResolveToCursorModel(input)
		if got != input {
			t.Errorf("ResolveToCursorModel(%q) = %q, want passthrough %q", input, got, input)
		}
	}
}

func TestResolveToCursorModel_Empty(t *testing.T) {
	if got := ResolveToCursorModel(""); got != "" {
		t.Errorf("ResolveToCursorModel(\"\") = %q, want empty", got)
	}
	if got := ResolveToCursorModel("  "); got != "" {
		t.Errorf("ResolveToCursorModel(\"  \") = %q, want empty", got)
	}
}

func TestGenerateDynamicAlias(t *testing.T) {
	tests := []struct {
		input string
		want  AnthropicAlias
		ok    bool
	}{
		{"opus-4.7", AnthropicAlias{"claude-opus-4-7", "Opus 4.7"}, true},
		{"sonnet-5.0-thinking", AnthropicAlias{"claude-sonnet-5-0-thinking", "Sonnet 5.0 (Thinking)"}, true},
		{"gpt-4o", AnthropicAlias{}, false},
		{"invalid", AnthropicAlias{}, false},
	}
	for _, tc := range tests {
		got, ok := generateDynamicAlias(tc.input)
		if ok != tc.ok {
			t.Errorf("generateDynamicAlias(%q) ok = %v, want %v", tc.input, ok, tc.ok)
			continue
		}
		if ok && (got.ID != tc.want.ID || got.Name != tc.want.Name) {
			t.Errorf("generateDynamicAlias(%q) = {%q, %q}, want {%q, %q}", tc.input, got.ID, got.Name, tc.want.ID, tc.want.Name)
		}
	}
}

func TestReverseDynamicAlias(t *testing.T) {
	tests := []struct {
		input string
		want  string
		ok    bool
	}{
		{"claude-opus-4-7", "opus-4.7", true},
		{"claude-sonnet-5-0-thinking", "sonnet-5.0-thinking", true},
		{"claude-opus-4-6", "opus-4.6", true},
		{"claude-opus-4.6", "", false},
		{"claude-haiku-4-5-20251001", "", false},
		{"some-model", "", false},
	}
	for _, tc := range tests {
		got, ok := reverseDynamicAlias(tc.input)
		if ok != tc.ok {
			t.Errorf("reverseDynamicAlias(%q) ok = %v, want %v", tc.input, ok, tc.ok)
			continue
		}
		if ok && got != tc.want {
			t.Errorf("reverseDynamicAlias(%q) = %q, want %q", tc.input, got, tc.want)
		}
	}
}
