package search

import (
	"context"
	"tercul/internal/domain"
	"time"

	"github.com/stretchr/testify/mock"
)

// SearchFilters defines the available filters for a search query.
type SearchFilters struct {
	Types      []string
	Languages  []string
	Categories []string
	Tags       []string
	Authors    []string
	DateFrom   *time.Time
	DateTo     *time.Time
}

// SearchMode defines the search mode (e.g., hybrid, bm25, vector).
type SearchMode string

const (
	SearchModeHybrid SearchMode = "hybrid"
	SearchModeBM25   SearchMode = "bm25"
	SearchModeVector SearchMode = "vector"
)

// SearchParams defines the parameters for a search query.
type SearchParams struct {
	Query    string
	Mode     SearchMode
	Filters  SearchFilters
	Limit    int
	Offset   int
	Concepts []string
}

// SearchResultItem represents a single item in the search results.
type SearchResultItem struct {
	Type   string
	Entity interface{}
	Score  float64
}

// SearchResults represents the results of a search query.
type SearchResults struct {
	Results      []SearchResultItem
	TotalResults int64
	Limit        int
	Offset       int
}

// SearchClient defines the interface for a search client.
type SearchClient interface {
	Search(ctx context.Context, params SearchParams) (*SearchResults, error)
	IndexWork(ctx context.Context, work *domain.Work, content string) error
}

// MockSearchClient is a mock implementation of the SearchClient interface.
type MockSearchClient struct {
	mock.Mock
}

// NewMockSearchClient creates a new mock search client.
func NewMockSearchClient() *MockSearchClient {
	return &MockSearchClient{}
}

// Search is a mock implementation of the Search method.
func (m *MockSearchClient) Search(ctx context.Context, params SearchParams) (*SearchResults, error) {
	args := m.Called(ctx, params)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).(*SearchResults), args.Error(1)
}

// IndexWork is a mock implementation of the IndexWork method.
func (m *MockSearchClient) IndexWork(ctx context.Context, work *domain.Work, content string) error {
	args := m.Called(ctx, work, content)
	return args.Error(0)
}
