package bootstrap

import (
	"tercul/internal/app"
	"tercul/internal/app/analytics"
	"tercul/internal/app/auth"
	"tercul/internal/app/author"
	"tercul/internal/app/authz"
	"tercul/internal/app/book"
	"tercul/internal/app/bookmark"
	"tercul/internal/app/category"
	"tercul/internal/app/collection"
	"tercul/internal/app/comment"
	"tercul/internal/app/contribution"
	"tercul/internal/app/like"
	"tercul/internal/app/localization"
	appsearch "tercul/internal/app/search"
	"tercul/internal/app/tag"
	"tercul/internal/app/translation"
	"tercul/internal/app/user"
	"tercul/internal/app/work"
	dbsql "tercul/internal/data/sql"
	domainsearch "tercul/internal/domain/search"
	"tercul/internal/jobs/linguistics"
	platform_auth "tercul/internal/platform/auth"
	"tercul/internal/platform/config"
	"tercul/internal/platform/search"

	"github.com/weaviate/weaviate-go-client/v5/weaviate"
	"gorm.io/gorm"
)

// NewWeaviateClient creates a new Weaviate client from config
func NewWeaviateClient(cfg *config.Config) (*weaviate.Client, error) {
	weaviateCfg := weaviate.Config{
		Host:   cfg.WeaviateHost,
		Scheme: cfg.WeaviateScheme,
	}
	return weaviate.NewClient(weaviateCfg)
}

// Dependencies holds all initialized dependencies
type Dependencies struct {
	Config            *config.Config
	Database          *gorm.DB
	WeaviateClient    *weaviate.Client
	SearchClient      domainsearch.SearchClient
	Repos             *dbsql.Repositories
	Application       *app.Application
	JWTManager        *platform_auth.JWTManager
	AnalysisRepo      *linguistics.GORMAnalysisRepository
	SentimentProvider *linguistics.GoVADERSentimentProvider
}

// Bootstrap initializes all application dependencies
func Bootstrap(cfg *config.Config, database *gorm.DB, weaviateClient *weaviate.Client) (*Dependencies, error) {
	// Create search client
	searchClient := search.NewWeaviateWrapper(weaviateClient, cfg.WeaviateHost, cfg.SearchAlpha)

	// Create repositories
	repos := dbsql.NewRepositories(database, cfg)

	// Create linguistics dependencies
	analysisRepo := linguistics.NewGORMAnalysisRepository(database)
	sentimentProvider, err := linguistics.NewGoVADERSentimentProvider()
	if err != nil {
		return nil, err
	}

	// Create platform components
	jwtManager := platform_auth.NewJWTManager(cfg)

	// Create application services
	analyticsService := analytics.NewService(repos.Analytics, analysisRepo, repos.Translation, repos.Work, sentimentProvider)
	localizationService := localization.NewService(repos.Localization)
	searchService := appsearch.NewService(searchClient, localizationService)
	authzService := authz.NewService(repos.Work, repos.Author, repos.User, repos.Translation)
	authorService := author.NewService(repos.Author)
	bookService := book.NewService(repos.Book, authzService)
	bookmarkService := bookmark.NewService(repos.Bookmark, analyticsService)
	categoryService := category.NewService(repos.Category)
	collectionService := collection.NewService(repos.Collection)
	commentService := comment.NewService(repos.Comment, authzService, analyticsService)
	contributionCommands := contribution.NewCommands(repos.Contribution, authzService)
	contributionService := contribution.NewService(contributionCommands)
	likeService := like.NewService(repos.Like, analyticsService)
	tagService := tag.NewService(repos.Tag)
	translationService := translation.NewService(repos.Translation, authzService)
	userService := user.NewService(repos.User, authzService, repos.UserProfile)
	authService := auth.NewService(repos.User, jwtManager)
	workService := work.NewService(repos.Work, repos.Author, repos.User, searchClient, authzService, analyticsService)

	// Create application
	application := app.NewApplication(
		authorService,
		bookService,
		bookmarkService,
		categoryService,
		collectionService,
		commentService,
		contributionService,
		likeService,
		tagService,
		translationService,
		userService,
		localizationService,
		authService,
		authzService,
		workService,
		searchService,
		analyticsService,
	)

	return &Dependencies{
		Config:            cfg,
		Database:          database,
		WeaviateClient:    weaviateClient,
		SearchClient:      searchClient,
		Repos:             repos,
		Application:       application,
		JWTManager:        jwtManager,
		AnalysisRepo:      analysisRepo,
		SentimentProvider: sentimentProvider,
	}, nil
}

// BootstrapWithMetrics initializes dependencies with metrics support
func BootstrapWithMetrics(cfg *config.Config, database *gorm.DB, weaviateClient *weaviate.Client) (*Dependencies, error) {
	// For now, same as Bootstrap, but can be extended if metrics are needed in bootstrap
	return Bootstrap(cfg, database, weaviateClient)
}
