package deps

import (
	"github.com/go-logr/logr"
	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/controller"
	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/infra/config"
	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/service"
	messageSvc "github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/service/message"
	messageBackCallSvc "github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/service/message_backcall"
	notifySvc "github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/service/notify"
	"go.uber.org/dig"
)

// type ServiceParams struct {
// 	dig.In
// 	Services []service.Service `group:"service"` // injected by dig
// }

// type ControllerParams struct {
// 	dig.In
// 	Controllers []controller.Controller `group:"controller"` // injected by dig
// }

type Deps struct {
	Container *dig.Container
}

func NewDeps() *Deps {
	return &Deps{
		Container: dig.New(),
	}
}

func (d *Deps) Init(conf *config.RootConfig, logger logr.Logger) error {
	// This line prevents controller-runtime from complaining about log.SetLogger never being called
	// logf.SetLogger(logger)
	bases := []any{
		func() *config.RootConfig { return conf },
		func() logr.Logger { return logger },
		newGormDB,
		newDBProvider,
		newAliClient,
		newLarkClientSet,
		newTwilioClient,
		newOlympusClient,
	}

	for _, f := range bases {
		if err := d.Container.Provide(f); err != nil {
			return err
		}
	}

	services := []any{
		notifySvc.NewService,
		messageBackCallSvc.NewService,
		messageSvc.NewService,
	}
	for _, f := range services {
		if err := d.Container.Provide(f); err != nil {
			return err
		}
	}
	if err := d.Container.Provide(service.NewManager); err != nil {
		return err
	}

	controllers := []any{
		controller.NewMessageController,
	}
	for _, constructor := range controllers {
		if err := d.Container.Provide(constructor, dig.Group("controller")); err != nil {
			return err
		}
	}
	if err := d.Container.Provide(controller.NewAPIServer); err != nil {
		return err
	}

	return nil
}
