package jobs

import (
	"context"
	"log/slog"

	"qycw/go-server/internal/bootstrap"
	"qycw/go-server/internal/domain/identity"
)

type Runner struct {
	app    *bootstrap.App
	logger *slog.Logger
}

func NewRunner(app *bootstrap.App, logger *slog.Logger) *Runner {
	return &Runner{app: app, logger: logger}
}

func (r *Runner) Run(ctx context.Context) error {
	r.logger.Info("worker runner started", "app", r.app.Config.AppName)
	provisionWorker := NewProvisionWorker(
		r.app.DB,
		r.logger,
		r.app.Config.ProvisionWorkerInterval,
		r.app.Config.ProvisionWorkerBatchSize,
		r.app.Config.ProvisionMaxAttempts,
		r.app.Plugins,
	)
	settlementWorker := NewSettlementWorker(
		r.app.DB,
		r.logger,
		r.app.Config.SettlementWorkerInterval,
		r.app.Config.SettlementWorkerBatchSize,
	)
	upstreamActionWorker := NewUpstreamActionWorker(
		r.app.DB,
		r.logger,
		r.app.Config.UpstreamActionWorkerInterval,
		r.app.Config.UpstreamActionWorkerBatchSize,
	)
	instanceLifecycleWorker := NewInstanceLifecycleWorker(
		r.app.DB,
		r.logger,
		0,
		0,
		r.app.Plugins,
	)
	identityService := identity.NewService(r.app.DB, r.app.Redis, r.app.Config, r.logger, r.app.Plugins)
	taskExecutor := NewTaskExecutor(r.app, r.logger, identityService)
	maintenanceWorker := NewMaintenanceWorker(r.app, r.logger, taskExecutor)
	provisionWorker.license = newWorkerLicenseGate(r.app.LicenseEval)
	settlementWorker.license = newWorkerLicenseGate(r.app.LicenseEval)
	upstreamActionWorker.license = newWorkerLicenseGate(r.app.LicenseEval)
	instanceLifecycleWorker.license = newWorkerLicenseGate(r.app.LicenseEval)
	maintenanceWorker.license = newWorkerLicenseGate(r.app.LicenseEval)

	errCh := make(chan error, 5)
	go func() { errCh <- provisionWorker.Run(ctx) }()
	go func() { errCh <- settlementWorker.Run(ctx) }()
	go func() { errCh <- upstreamActionWorker.Run(ctx) }()
	go func() { errCh <- instanceLifecycleWorker.Run(ctx) }()
	go func() { errCh <- maintenanceWorker.Run(ctx) }()

	select {
	case <-ctx.Done():
		return nil
	case err := <-errCh:
		return err
	}
}
