package main

import (
	"context"
	"errors"
	"os/signal"
	"strings"
	"syscall"

	queueapp "wucher/internal/app/queueing"
	appworker "wucher/internal/app/worker"
	"wucher/internal/config"
	"wucher/internal/queue"
	mysqlrepo "wucher/internal/repository/mysql"
	s3repo "wucher/internal/repository/s3"
	"wucher/internal/resilience"
	"wucher/internal/service"
	"wucher/internal/shared/pkg/logger"
)
 
func runFileWorker(appCfg config.AppConfig) error {
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	appLogger := logger.New(appCfg.Logging).With("component", "worker", "job", "file_processing")
	resCfg := appCfg.Resilience
	fileQueueCfg := appCfg.FileQueue
	fileSQSCfg := appCfg.FileSQS
	if err := config.ValidateDistinctQueueURLs(appCfg.SQS, fileSQSCfg); err != nil {
		return err
	}
	if strings.TrimSpace(fileSQSCfg.QueueURL) == "" {
		return errors.New("FILE_SQS_QUEUE_URL is required for file worker")
	}
	db, err := mysqlrepo.Connect(appCfg.MySQL)
	if err != nil {
		return err
	}

	fileRepo := mysqlrepo.NewFileManagerFileRepository(db)
	sqsBreaker := resilience.NewExecutor("sqs", resCfg.SQS, appLogger, resilience.ClassifySQSError)
	consumer, serializer, err := queueapp.NewFileProcessingConsumer(ctx, fileQueueCfg, fileSQSCfg, sqsBreaker)
	if err != nil {
		return err
	}
	idempotency := queueapp.NewIdempotencyStoreWithPrefix(db, fileQueueCfg.IdempotencyKeyPrefix)
	useCaseDeps := service.FileProcessingUseCaseDependencies{
		Logger:           appLogger,
		FileStatusEvents: fileRepo,
		GotenbergURL:     appCfg.Gotenberg.URL,
	}
	fileStorageCfg := appCfg.FileStorage
	if fileStorageCfg.Bucket != "" && fileStorageCfg.Region != "" {
		storage, err := s3repo.NewFileObjectStorage(ctx, fileStorageCfg)
		if err != nil {
			return err
		}
		useCaseDeps.Storage = storage
	}
	useCase := service.NewFileProcessingUseCase(fileRepo, useCaseDeps)
	handler := queue.NewFileProcessingJobQueueHandler(useCase, service.IsFileProcessingPermanentError)
	var dispatcher *appworker.FileProcessingOutboxDispatcher
	if fileQueueCfg.OutboxEnabled {
		rawProducer, err := queueapp.NewQueueProducer(ctx, fileSQSCfg, sqsBreaker, "outbox_dispatcher")
		if err != nil {
			return err
		}
		dispatcher = appworker.NewFileProcessingOutboxDispatcher(fileQueueCfg, fileRepo, rawProducer, appLogger)
	}
	runner := appworker.NewFileProcessingRunner(fileQueueCfg, consumer, serializer, handler, idempotency, dispatcher, appLogger)

	appLogger.Info("file worker started",
		"backend", "sqs",
		"monitor_addr", fileQueueCfg.WorkerMonitorAddr,
		"queue_url", fileSQSCfg.QueueURL,
		"outbox_enabled", fileQueueCfg.OutboxEnabled,
	)
	if err := runner.Start(ctx); err != nil {
		return err
	}
	appLogger.Info("file worker stopped")
	return nil
}
