package router

import (
	"strings"
	"unicode"

	"github.com/kami/maven/internal/lexicon"
)

var possessionQuestionWords = func() map[string]bool {
	words := make(map[string]bool)
	for _, word := range append(lexicon.Interrogatives(), lexicon.NarrativeRequests()...) {
		words[word] = true
	}
	return words
}()

// PossessionStatementGrammar recognises the Russian possessive construction
// “у меня …” as a statement to remember. Russian has no present-tense “have”:
// the preposition and genitive pronoun are the grammatical predicate, so a
// sentence such as “у меня новый ноутбук” contains no verb for a generic
// sentence parser to anchor on. Both the hash floor and the deployed routing
// heads have measured this exact shape as a query and would try to answer it
// instead of recording it.
//
// This is a token grammar, not a phrase regexp or a noun list. The two-token
// frame is a closed grammatical construction and the remainder stays open.
// Questions and explicit capture/reminder/narrative requests retain their
// narrower routes; only a plain declaration is claimed.
func PossessionStatementGrammar() Grammar {
	return Grammar{Name: "possession-statement", Decide: possessionStatementDecision}
}

func possessionStatementDecision(utterance string) (Decision, bool) {
	tokens := planTokens(utterance)
	if len(tokens) < 3 || tokens[0] != "у" || tokens[1] != "меня" {
		return Decision{}, false
	}
	if possessionQuestionShaped(utterance) || CarriesCaptureVerb(utterance) || carriesReminderVerbTokens(tokens) {
		return Decision{}, false
	}
	return Decision{
		Stage:      0,
		Intent:     IntentNote,
		Confidence: 1,
		Slots:      Slots{Text: utterance},
	}, true
}

// possessionQuestionShaped is the question half of this grammar over Russian
// word structure. IsQuestionShaped intentionally tokenises punctuation away,
// which makes the interrogative root in indefinite pronouns look like a
// question: “что-то сломалось”, “кто-нибудь пришёл”, “когда-то работало”. Here
// that would defeat the open possession statement this grammar exists for.
//
// Hyphenated indefinite forms are a closed grammatical construction, not a
// phrase list: interrogative+{то, либо, нибудь}, or кое+interrogative. Every
// other exact interrogative/narrative token remains a question, as does a
// question mark. No noun or payload vocabulary is involved.
func possessionQuestionShaped(text string) bool {
	if strings.HasSuffix(strings.TrimSpace(text), "?") {
		return true
	}
	for _, lexeme := range possessionLexemes(text) {
		if possessionQuestionWords[lexeme] {
			return true
		}
		parts := strings.Split(lexeme, "-")
		if indefiniteQuestionCompound(parts) {
			continue
		}
		for _, part := range parts {
			if possessionQuestionWords[part] {
				return true
			}
		}
	}
	return false
}

func possessionLexemes(text string) []string {
	return strings.FieldsFunc(strings.ToLower(text), func(r rune) bool {
		return !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '-'
	})
}

func indefiniteQuestionCompound(parts []string) bool {
	if len(parts) != 2 {
		return false
	}
	if parts[0] == "кое" && possessionQuestionWords[parts[1]] {
		return true
	}
	if !possessionQuestionWords[parts[0]] {
		return false
	}
	switch parts[1] {
	case "то", "либо", "нибудь":
		return true
	default:
		return false
	}
}

func carriesReminderVerbTokens(tokens []string) bool {
	for _, verb := range lexicon.ReminderVerbs() {
		if hasTok(tokens, verb) {
			return true
		}
	}
	return false
}
