package phraser

import (
	"math/rand"
	"strings"
	"testing"
)

func TestQueriesLoad(t *testing.T) {
	q, err := LoadQueries(rand.NewSource(1))
	if err != nil {
		t.Fatalf("LoadQueries: %v", err)
	}
	for _, k := range queryKeys {
		if got := q.Say(k, nil); got == "" {
			t.Errorf("%s says nothing", k)
		}
	}
}

// The bug: net_empty carried {tail} in every variant, and a scan that finished
// the whole range has no caveat to put there. Whatever the file says, an answer
// he can hear has to come out — never braces, never nothing.
func TestNetEmptySaysSomethingWithNoTail(t *testing.T) {
	q, err := LoadQueries(rand.NewSource(1))
	if err != nil {
		t.Fatalf("LoadQueries: %v", err)
	}
	for _, vars := range []map[string]string{nil, {"tail": ""}} {
		for i := 0; i < 20; i++ {
			got := q.Say(QueryNetEmpty, vars)
			if got == "" || strings.ContainsAny(got, "{}") {
				t.Fatalf("net_empty with vars %v said %q", vars, got)
			}
		}
	}
}

// The other half: a caveat he was given is not dropped for a shorter wording.
func TestNetEmptyKeepsTheTailItIsGiven(t *testing.T) {
	q, err := LoadQueries(rand.NewSource(1))
	if err != nil {
		t.Fatalf("LoadQueries: %v", err)
	}
	const tail = ", но успела посмотреть не всю сеть"
	for i := 0; i < 20; i++ {
		if got := q.Say(QueryNetEmpty, map[string]string{"tail": tail}); !strings.Contains(got, tail) {
			t.Fatalf("net_empty dropped the tail: %q", got)
		}
	}
}

// query_unknown means she looked and found nothing. The phraser's fallback
// means she failed to phrase an answer she had. Two causes, two sentences, or
// the distinction the two files exist for is unobservable from the outside.
func TestQueryUnknownNeverRepeatsAPhrasingFallback(t *testing.T) {
	q, err := LoadQueries(rand.NewSource(1))
	if err != nil {
		t.Fatalf("LoadQueries: %v", err)
	}
	f, err := LoadFallbacks(rand.NewSource(1))
	if err != nil {
		t.Fatalf("LoadFallbacks: %v", err)
	}
	failures := map[string]bool{}
	for _, v := range f.Variants() {
		failures[v] = true
	}
	for _, v := range q.d.VariantsOf(QueryUnknown) {
		if failures[v] {
			t.Errorf("query_unknown variant %q is also a phrasing failure line", v)
		}
	}
}

// The weather line splits the count into a number and a noun, so a variant that
// says the temperature without {word} is the hardcoded "градусов" coming back.
func TestWeatherLineCountsWithTheHelper(t *testing.T) {
	q, err := LoadQueries(rand.NewSource(1))
	if err != nil {
		t.Fatalf("LoadQueries: %v", err)
	}
	for _, v := range q.d.VariantsOf(QueryWeatherNow) {
		if strings.Contains(v, "градус") {
			t.Errorf("weather_now variant %q spells the noun out instead of using {word}", v)
		}
	}
	got := q.Say(QueryWeatherNow, map[string]string{
		"location": "Москва", "temp": "1", "word": Degrees(1), "condition": "ясно",
	})
	if !strings.Contains(got, "1 градус,") {
		t.Errorf("weather_now said %q, want the singular noun", got)
	}
}

// No line spoken to him names a config key. She asks instead.
func TestNoQueryLineRecitesAConfigPath(t *testing.T) {
	q, err := LoadQueries(rand.NewSource(1))
	if err != nil {
		t.Fatalf("LoadQueries: %v", err)
	}
	for _, v := range q.Variants() {
		if strings.Contains(v, "voice.") || strings.Contains(v, "_location") {
			t.Errorf("variant %q says a config path out loud", v)
		}
	}
}
