package linguistics

import (
	"tercul/internal/platform/cache"
	"tercul/internal/platform/config"

	"gorm.io/gorm"
)

// LinguisticsFactory provides easy access to all linguistics components
type LinguisticsFactory struct {
	textAnalyzer        TextAnalyzer
	analysisCache       AnalysisCache
	analysisRepo        AnalysisRepository
	workAnalysisService WorkAnalysisService
	analyzer            Analyzer
	sentimentProvider   SentimentProvider
}

// NewLinguisticsFactory creates a new LinguisticsFactory with all components
func NewLinguisticsFactory(
	cfg *config.Config,
	db *gorm.DB,
	cache cache.Cache,
	concurrency int,
	cacheEnabled bool,
	sentimentProvider SentimentProvider,
) *LinguisticsFactory {
	// Create text analyzer and wire providers (prefer external libs when available)
	textAnalyzer := NewBasicTextAnalyzer()

	// Wire sentiment provider
	textAnalyzer = textAnalyzer.WithSentimentProvider(sentimentProvider)

	// Wire language detector: lingua-go (configurable)
	if cfg.NLPUseLingua {
		textAnalyzer = textAnalyzer.WithLanguageDetector(NewLinguaLanguageDetector())
	}

	// Wire keyword provider: lightweight TF-IDF approximation (configurable)
	if cfg.NLPUseTFIDF {
		textAnalyzer = textAnalyzer.WithKeywordProvider(NewTFIDFKeywordProvider())
	}

	// Create cache components
	memoryCache := NewMemoryAnalysisCache(cfg, cacheEnabled)
	redisCache := NewRedisAnalysisCache(cfg, cache, cacheEnabled)
	analysisCache := NewCompositeAnalysisCache(memoryCache, redisCache, cacheEnabled)

	// Create repository
	analysisRepo := NewGORMAnalysisRepository(db)

	// Create work analysis service
	workAnalysisService := NewWorkAnalysisService(
		textAnalyzer,
		analysisCache,
		analysisRepo,
		concurrency,
		cacheEnabled,
	)

	// Create analyzer that combines text analysis and work analysis
	analyzer := NewBasicAnalyzer(
		textAnalyzer,
		workAnalysisService,
		cache,
		concurrency,
		cacheEnabled,
	)

	return &LinguisticsFactory{
		textAnalyzer:        textAnalyzer,
		analysisCache:       analysisCache,
		analysisRepo:        analysisRepo,
		workAnalysisService: workAnalysisService,
		analyzer:            analyzer,
		sentimentProvider:   sentimentProvider,
	}
}

// GetTextAnalyzer returns the text analyzer
func (f *LinguisticsFactory) GetTextAnalyzer() TextAnalyzer {
	return f.textAnalyzer
}

// GetAnalysisCache returns the analysis cache
func (f *LinguisticsFactory) GetAnalysisCache() AnalysisCache {
	return f.analysisCache
}

// GetAnalysisRepository returns the analysis repository
func (f *LinguisticsFactory) GetAnalysisRepository() AnalysisRepository {
	return f.analysisRepo
}

// GetWorkAnalysisService returns the work analysis service
func (f *LinguisticsFactory) GetWorkAnalysisService() WorkAnalysisService {
	return f.workAnalysisService
}

// GetAnalyzer returns the analyzer
func (f *LinguisticsFactory) GetAnalyzer() Analyzer {
	return f.analyzer
}

// GetSentimentProvider returns the sentiment provider
func (f *LinguisticsFactory) GetSentimentProvider() SentimentProvider {
	return f.sentimentProvider
}