package gtm

import (
	"fmt"
	"strings"
	"unicode"

	"github.com/go-logr/logr"
	"github.com/tidbcloud/devops/entity/userbehavior"
	"github.com/tidbcloud/devops/pkg/infra/config"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
)

type ReferenceMatcher struct {
	logger   logr.Logger
	profiles []config.UseCaseProfile
}

func NewReferenceMatcher(logger logr.Logger, profiles []config.UseCaseProfile) *ReferenceMatcher {
	return &ReferenceMatcher{
		logger:   logger,
		profiles: profiles,
	}
}

func (m *ReferenceMatcher) Match(lead *userbehavior.GTMLead) MatchResult {
	// Try each profile in order of priority
	for _, profile := range m.profiles {
		if m.matchesProfile(lead, profile) {
			return MatchResult{
				Matched:            true,
				UseCaseProfile:     profile.Name,
				CustomerReferences: profile.CustomerReferences,
				Reason:             fmt.Sprintf("Matched %s use case", profile.Name),
			}
		}
	}

	return MatchResult{
		Matched: false,
		Reason:  "No matching use case profile found",
	}
}

func (m *ReferenceMatcher) matchesProfile(lead *userbehavior.GTMLead, profile config.UseCaseProfile) bool {
	// Required keywords must match the company vertical to avoid broad business-model-only hits.
	vertical := pointer.Deref(lead.Vertical, "")
	businessModelLower := strings.ToLower(pointer.Deref(lead.BusinessModel, ""))

	keywordMatch := false
	for _, keyword := range profile.RequiredKeywords {
		if containsKeywordPhrase(vertical, keyword) {
			keywordMatch = true
			break
		}
	}

	if !keywordMatch {
		return false
	}

	// Check preferred business model
	if profile.PreferredBusinessModel != "" {
		if !strings.Contains(businessModelLower, profile.PreferredBusinessModel) {
			return false
		}
	}

	return true
}

func containsKeywordPhrase(text, keyword string) bool {
	textTokens := tokenizeForKeywordMatch(text)
	keywordTokens := tokenizeForKeywordMatch(keyword)
	if len(textTokens) == 0 || len(keywordTokens) == 0 {
		return false
	}

	for i := 0; i+len(keywordTokens) <= len(textTokens); i++ {
		matched := true
		for j := range keywordTokens {
			if textTokens[i+j] != keywordTokens[j] {
				matched = false
				break
			}
		}
		if matched {
			return true
		}
	}

	return false
}

func tokenizeForKeywordMatch(s string) []string {
	return strings.FieldsFunc(strings.ToLower(s), func(r rune) bool {
		return !unicode.IsLetter(r) && !unicode.IsDigit(r)
	})
}
