package search

import (
	"context"
	"tercul/internal/domain"
	"tercul/internal/platform/search"
)

// BleveSearchService provides keyword and exact-match search capabilities
// Complements Weaviate's vector/semantic search with traditional full-text search
type BleveSearchService interface {
	IndexTranslation(ctx context.Context, translation domain.Translation) error
	IndexAllTranslations(ctx context.Context) error
	SearchTranslations(ctx context.Context, query string, filters map[string]string, limit int) ([]TranslationSearchResult, error)
}

type TranslationSearchResult struct {
	ID               uint
	Score            float64
	Title            string
	Content          string
	Language         string
	TranslatableID   uint
	TranslatableType string
}

type bleveSearchService struct {
	translationRepo domain.TranslationRepository
}

func NewBleveSearchService(translationRepo domain.TranslationRepository) BleveSearchService {
	return &bleveSearchService{
		translationRepo: translationRepo,
	}
}

func (s *bleveSearchService) IndexTranslation(ctx context.Context, translation domain.Translation) error {
	return search.BleveClient.AddTranslation(translation)
}

func (s *bleveSearchService) IndexAllTranslations(ctx context.Context) error {
	// Get all translations from the database and index them
	translations, err := s.translationRepo.ListAll(ctx)
	if err != nil {
		return err
	}

	for _, translation := range translations {
		if err := search.BleveClient.AddTranslation(translation); err != nil {
			return err
		}
	}

	return nil
}

func (s *bleveSearchService) SearchTranslations(ctx context.Context, query string, filters map[string]string, limit int) ([]TranslationSearchResult, error) {
	results, err := search.BleveClient.Search(query, filters, limit)
	if err != nil {
		return nil, err
	}

	var searchResults []TranslationSearchResult
	for _, hit := range results.Hits {
		// Extract fields from the hit
		fields := hit.Fields
		result := TranslationSearchResult{
			Score: hit.Score,
		}

		// Safely extract fields with type assertions
		if id, ok := fields["id"].(float64); ok {
			result.ID = uint(id)
		}
		if title, ok := fields["title"].(string); ok {
			result.Title = title
		}
		if content, ok := fields["content"].(string); ok {
			result.Content = content
		}
		if language, ok := fields["language"].(string); ok {
			result.Language = language
		}
		if translatableID, ok := fields["translatable_id"].(float64); ok {
			result.TranslatableID = uint(translatableID)
		}
		if translatableType, ok := fields["translatable_type"].(string); ok {
			result.TranslatableType = translatableType
		}

		searchResults = append(searchResults, result)
	}

	return searchResults, nil
}
