package jobs

import (
	"context"

	"github.com/rs/zerolog/log"
	"github.com/warmbly/warmbly/internal/app/advanced"
	warmupapp "github.com/warmbly/warmbly/internal/app/warmup"
	workerapp "github.com/warmbly/warmbly/internal/app/worker"
	"github.com/warmbly/warmbly/internal/events"
	"github.com/warmbly/warmbly/internal/infrastructure/cache"
	"github.com/warmbly/warmbly/internal/infrastructure/codec"
	"github.com/warmbly/warmbly/internal/infrastructure/eventbus"
	"github.com/warmbly/warmbly/internal/infrastructure/kafka"
	"github.com/warmbly/warmbly/internal/infrastructure/pubsub"
	"github.com/warmbly/warmbly/internal/models"
	"github.com/warmbly/warmbly/internal/repository"
)

type JobsService struct {
	// Bus delivers the jobs.worker-events stream (Kafka or NATS).
	Bus eventbus.EventBus
	// Codec decodes bus payloads (jobs.worker-events); it must match the
	// CODEC_PROVIDER the producing services run with.
	Codec                       codec.Codec
	UniboxRepository            repository.UniboxRepository
	MailboxRepository           repository.MailboxRepository
	EmailRepository             repository.EmailRepository
	EmailHistoryIDRepository    repository.EmailHistoryIDRepository
	EmailGraphDeltaRepository   repository.EmailGraphDeltaRepository
	EmailSyncStateRepository    repository.EmailSyncStateRepository
	EmailAccountErrorRepository repository.EmailAccountErrorRepository
	WarmupRepo                  repository.WarmupRepository
	WarmupContentRepo           repository.WarmupContentRepository
	WarmupEngagementRepo        repository.WarmupEngagementRepository
	WarmupService               warmupapp.Service
	WorkerRepo                  repository.WorkerRepository

	// Publisher for sending events to workers
	Publisher events.Publisher

	// Pub/Sub for real-time notifications to users
	StreamingPublisher *pubsub.StreamingPublisher
	AdvancedService    advanced.Service

	// Cache for dead worker detection
	Cache *cache.Cache

	// AdminRepo for writing audit-log rows when the dead-worker job
	// auto-reassigns email accounts (optional — heartbeat sync also writes
	// here so admins can see why their fleet moved). Nil disables logging.
	AdminRepo repository.AdminRepository

	// AssignmentService is used by the risk rebalancer to pick replacement
	// workers when a mailbox's risk band changes. Nil disables the job.
	AssignmentService workerapp.WorkerAssignmentService

	// Notifier tells affected orgs (members with manage_emails) when the
	// dead-worker job moves or strands their mailboxes. Nil disables it.
	Notifier OrgNotifier

	// Send-outcome handling (EMAIL_SENT / EMAIL_FAILED from workers). The task
	// and campaign progress the control plane stamped at hand-off are walked
	// back here when a worker reports it could not send. Nil TaskRepo disables
	// the handlers.
	TaskRepo             repository.TaskRepository
	CampaignRepo         repository.CampaignRepository
	CampaignProgressRepo repository.CampaignProgressRepository
	CampaignLogRepo      repository.CampaignLogRepository
	ContactRepo          repository.ContactRepository

	eventHandlers map[models.JobEventType]func(ctx context.Context, body any) error
}

func (s *JobsService) Start(ctx context.Context) {
	if err := s.Bus.Subscribe(ctx, []string{kafka.TopicWorkerEvents}, "consumer-group", s.receive); err != nil {
		log.Error().Err(err).Msg("consumer: worker-events subscription ended")
	}
}
