package router

import (
	"context"
	"testing"
)

// agendaRouter wires both grammar sets in the order the daemon wires them
// (voicewire.go): the clock rules first, the agenda rules after, so a test
// that passes here is a test of the deployed precedence.
func agendaRouter(t *testing.T) *Router {
	t.Helper()
	r := newTestRouter(t, 0.0)
	r.grammars = append(r.grammars, SystemTimeDateGrammars()...)
	r.grammars = append(r.grammars, AgendaQueryGrammars()...)
	return r
}

// An agenda question is answered from the calendar, which lives in the query
// chain. Routed to system it reaches replySystem, which has no agenda arm and
// says "пока не умею" — seen on the deployed daemon, 01-08-2026.
func TestAgendaQuestionsRouteToQuery(t *testing.T) {
	r := agendaRouter(t)
	for _, u := range []string{
		"что у меня сегодня",
		"что у меня в календаре сегодня",
		"что у меня стоит в календаре на послезавтра",
		"какие у меня встречи завтра",
		"покажи расписание на среду",
	} {
		d, err := r.Route(context.Background(), u, refNow())
		if err != nil {
			t.Fatalf("route(%q): %v", u, err)
		}
		if d.Intent != IntentQuery {
			t.Errorf("route(%q) = %s, want query", u, d.Intent)
		}
	}
}

// The clock rules keep their utterances. They are registered first and the
// agenda patterns do not match them, so both statements have to hold.
func TestAgendaGrammarsLeaveTheClockAlone(t *testing.T) {
	r := agendaRouter(t)
	for _, u := range []string{
		"какой сегодня день",
		"какое сегодня число",
		"который час",
		"сколько сейчас времени",
	} {
		d, err := r.Route(context.Background(), u, refNow())
		if err != nil {
			t.Fatalf("route(%q): %v", u, err)
		}
		if d.Intent != IntentSystem {
			t.Errorf("route(%q) = %s, want system", u, d.Intent)
		}
	}
}

// The agenda pattern is anchored and needs the possessive, so an ordinary
// statement that happens to contain "у меня" is not swallowed.
func TestAgendaGrammarSparesStatements(t *testing.T) {
	r := agendaRouter(t)
	for _, u := range []string{
		"у меня кончилась вода",
		"напомни мне завтра позвонить маме",
	} {
		d, err := r.Route(context.Background(), u, refNow())
		if err != nil {
			t.Fatalf("route(%q): %v", u, err)
		}
		if d.Stage == 0 && d.Intent == IntentQuery {
			t.Errorf("route(%q) was claimed by the agenda grammar", u)
		}
	}
}

// The two shapes that carried no question mark and no interrogative, so the
// model saw them first and called them facts (Vikunja #498).
func TestNarrativeGrammarsRouteToQuery(t *testing.T) {
	r := agendaRouter(t)
	r.grammars = append(r.grammars, NarrativeQueryGrammars()...)
	for _, u := range []string{
		"что дальше?",
		"и что там дальше",
		"what's next?",
		"расскажи про битву при Ватерлоо",
		"объясни как работает дизель",
		"опиши Ватерлоо",
	} {
		d, err := r.Route(context.Background(), u, refNow())
		if err != nil {
			t.Fatalf("%q: %v", u, err)
		}
		if d.Intent != IntentQuery || d.Stage != 0 {
			t.Errorf("%q routed intent=%s stage=%d, want query at stage 0", u, d.Intent, d.Stage)
		}
	}
}

// The tomorrow form and the bare event noun. Both were measured answering
// "пока не умею" on the deployed daemon, 02-08-2026, while the same question
// about today worked — the first rule set needed "у меня" or a calendar noun
// and these phrasings carry neither (Vikunja #471).
func TestAgendaCoversOtherDaysAndNamedEvents(t *testing.T) {
	r := agendaRouter(t)
	for _, u := range []string{
		"какие планы на завтра?",
		"какие планы на послезавтра",
		"что по делам в среду",
		"какие планы на выходные",
		"когда планёрка?",
		"во сколько созвон",
		"когда будет совещание",
	} {
		d, err := r.Route(context.Background(), u, refNow())
		if err != nil {
			t.Fatalf("route(%q): %v", u, err)
		}
		if d.Intent != IntentQuery {
			t.Errorf("route(%q) = %s, want query", u, d.Intent)
		}
	}
}

// A narrative verb next to a capture verb is him asking for a note. Stage 0
// declines and the extractor gets its turn.
func TestNarrativeGrammarLeavesCapturesAlone(t *testing.T) {
	r := agendaRouter(t)
	r.grammars = append(r.grammars, NarrativeQueryGrammars()...)
	d, err := r.Route(context.Background(), "расскажи и запиши что я пил воду", refNow())
	if err != nil {
		t.Fatal(err)
	}
	if d.Stage == 0 && d.Intent == IntentQuery {
		t.Errorf("stage 0 claimed a capture: %+v", d)
	}
}

// The two new rules are narrow on purpose. A world question that opens with
// "когда" is not an agenda question, and telling her about a plan is not
// asking about one.
func TestAgendaGrammarsLeaveTheWorldAlone(t *testing.T) {
	r := agendaRouter(t)
	for _, u := range []string{
		"когда была битва при ватерлоо",
		"когда изобрели телефон",
	} {
		d, err := r.Route(context.Background(), u, refNow())
		if err != nil {
			t.Fatalf("route(%q): %v", u, err)
		}
		if d.Stage == 0 {
			t.Errorf("route(%q) was claimed at stage 0 as %s", u, d.Intent)
		}
	}
}
