package tts

import (
	"testing"
)

func TestConfigValidate(t *testing.T) {
	tests := []struct {
		name    string
		cfg     Config
		wantErr bool
	}{
		{
			name:    "empty config",
			cfg:     Config{},
			wantErr: true,
		},
		{
			name: "missing URL",
			cfg: Config{
				Voice: "af_heart",
			},
			wantErr: true,
		},
		{
			name: "missing voice",
			cfg: Config{
				URL: "http://localhost:8880",
			},
			wantErr: true,
		},
		{
			name: "invalid timeout",
			cfg: Config{
				URL:     "http://localhost:8880",
				Voice:   "af_heart",
				Timeout: "not-a-duration",
			},
			wantErr: true,
		},
		{
			name: "valid minimal config",
			cfg: Config{
				URL:   "http://localhost:8880",
				Voice: "af_heart",
			},
			wantErr: false,
		},
		{
			name: "valid config with timeout",
			cfg: Config{
				URL:     "http://localhost:8880",
				Voice:   "af_heart",
				Timeout: "120s",
			},
			wantErr: false,
		},
		{
			name: "valid config with voice map",
			cfg: Config{
				URL:   "http://localhost:8880",
				Voice: "af_heart",
				VoiceMap: map[string]string{
					"english": "af_heart",
					"chinese": "zf_xiaobei",
				},
			},
			wantErr: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := tt.cfg.Validate()
			if (err != nil) != tt.wantErr {
				t.Errorf(
					"Validate() error = %v, wantErr %v",
					err, tt.wantErr,
				)
			}
		})
	}
}

func TestNewClient(t *testing.T) {
	tests := []struct {
		name    string
		cfg     Config
		wantErr bool
	}{
		{
			name:    "invalid config",
			cfg:     Config{},
			wantErr: true,
		},
		{
			name: "valid config without timeout",
			cfg: Config{
				URL:   "http://localhost:8880",
				Voice: "af_heart",
			},
			wantErr: false,
		},
		{
			name: "valid config with timeout",
			cfg: Config{
				URL:     "http://localhost:8880",
				Voice:   "af_heart",
				Timeout: "90s",
			},
			wantErr: false,
		},
		{
			name: "valid config with custom voice map",
			cfg: Config{
				URL:   "http://localhost:8880",
				Voice: "af_heart",
				VoiceMap: map[string]string{
					"english": "custom_en",
					"french":  "custom_fr",
				},
			},
			wantErr: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			client, err := NewClient(tt.cfg, nil)
			if (err != nil) != tt.wantErr {
				t.Errorf(
					"NewClient() error = %v, wantErr %v",
					err, tt.wantErr,
				)
				return
			}
			if !tt.wantErr && client == nil {
				t.Error("NewClient() returned nil client")
			}
		})
	}
}

func TestSelectVoice(t *testing.T) {
	tests := []struct {
		name     string
		voiceMap map[string]string
		lang     string
		want     string
	}{
		{
			name:     "default map english",
			voiceMap: nil,
			lang:     "english",
			want:     "af_heart",
		},
		{
			name:     "default map chinese",
			voiceMap: nil,
			lang:     "chinese",
			want:     "zf_xiaobei",
		},
		{
			name:     "default map japanese",
			voiceMap: nil,
			lang:     "japanese",
			want:     "jf_alpha",
		},
		{
			name:     "default map unknown language",
			voiceMap: nil,
			lang:     "klingon",
			want:     "",
		},
		{
			name: "custom map",
			voiceMap: map[string]string{
				"english": "custom_english",
				"german":  "custom_german",
			},
			lang: "english",
			want: "custom_english",
		},
		{
			name: "custom map missing language",
			voiceMap: map[string]string{
				"english": "custom_english",
			},
			lang: "french",
			want: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			cfg := Config{
				URL:      "http://localhost:8880",
				Voice:    "af_heart",
				VoiceMap: tt.voiceMap,
			}
			client, err := NewClient(cfg, nil)
			if err != nil {
				t.Fatalf("NewClient() error = %v", err)
			}

			got := client.SelectVoice(tt.lang)
			if got != tt.want {
				t.Errorf(
					"SelectVoice(%q) = %q, want %q",
					tt.lang, got, tt.want,
				)
			}
		})
	}
}

func TestDefaultVoiceMap(t *testing.T) {
	// Verify that DefaultVoiceMap contains expected entries.
	expected := map[string]string{
		"english":  "af_heart",
		"chinese":  "zf_xiaobei",
		"japanese": "jf_alpha",
		"spanish":  "ef_dora",
		"french":   "ff_siwis",
		"korean":   "kf_sarah",
	}

	for lang, voice := range expected {
		if got := defaultVoices[lang]; got != voice {
			t.Errorf(
				"DefaultVoiceMap[%q] = %q, want %q",
				lang, got, voice,
			)
		}
	}
}
