package controller

import (
	"context"
	"time"

	"github.com/tidbcloud/chaos-svc/pkg/application/cmd/backend"
	"github.com/tidbcloud/chaos-svc/pkg/application/cmd/experiment"
	"github.com/tidbcloud/pkgv2/log"
	"github.com/tidbcloud/pkgv2/worker"
	"go.uber.org/zap"
)

type GlobalWorker struct {
	workers []*worker.PeriodWorker
}

func NewGlobalWorker() (*GlobalWorker, error) {
	globalWorker := &GlobalWorker{}

	err := DiCall(func(
		syncWorkflowWorker *SyncWorkflowWorker,
		syncBackendWorker *SyncBackendWorker,
	) {
		globalWorker.workers = []*worker.PeriodWorker{
			worker.NewPeriodWorker(log.With(zap.String("worker", "sync_backend")), time.Second*10, syncBackendWorker.Run),
			worker.NewPeriodWorker(log.With(zap.String("worker", "sync_workflow")), time.Second*10, syncWorkflowWorker.Run),
		}
	})
	if err != nil {
		panic(err)
	}
	return globalWorker, nil
}

func (w *GlobalWorker) Start() {
	for _, item := range w.workers {
		item.Start()
	}
}

type SyncBackendWorker struct {
	syncBackendFromInfraSvc *backend.SyncBackendFromInfraSvc
}

func NewSyncBackendWorker(syncBackendFromInfraSvc *backend.SyncBackendFromInfraSvc) *SyncBackendWorker {
	return &SyncBackendWorker{syncBackendFromInfraSvc: syncBackendFromInfraSvc}
}

func (w *SyncBackendWorker) Run(ctx context.Context) error {
	logger := log.WithContextS(ctx)
	if err := w.syncBackendFromInfraSvc.Execute(ctx); err != nil {
		logger.Errorf("syncBackendFromInfra failed: %s", err)
	}
	return nil
}

type SyncWorkflowWorker struct {
	syncWorkflowFromInfraSvc *experiment.SyncWorkflowFromInfraSvc
}

func NewSyncWorkflowWorker(syncWorkflowFromInfraSvc *experiment.SyncWorkflowFromInfraSvc) *SyncWorkflowWorker {
	return &SyncWorkflowWorker{syncWorkflowFromInfraSvc: syncWorkflowFromInfraSvc}
}

func (w *SyncWorkflowWorker) Run(ctx context.Context) error {
	logger := log.WithContextS(ctx)
	if err := w.syncWorkflowFromInfraSvc.Execute(ctx); err != nil {
		logger.Errorf("syncWorkflowFromInfra failed: %s", err)
	}
	return nil
}

// TODO: send message to feishu if backend install failed
// TODO: send message to feishu if workflow is failed
