package deps

import (
	"context"

	"go.uber.org/dig"

	"github.com/tidbcloud/aisupport/services/jsm-syncer/config"
	"github.com/tidbcloud/aisupport/services/jsm-syncer/internal/app"
	adminhdl "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/app/handlers/admin"
	ingesthdl "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/app/handlers/ingest"
	queryhdl "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/app/handlers/query"
	"github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services"
	accountresolver "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/accountresolver"
	atlassiansyncsvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/atlassiansync"
	eventconsumersvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/eventconsumer"
	querysvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/query"
	reconciliationsvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/reconciliation"
	rolecomputersvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/rolecomputer"
	syncstatesvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/syncstate"
	technicalrolewhitelistsvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/technicalrolewhitelist"
	usersvc "github.com/tidbcloud/aisupport/services/jsm-syncer/internal/services/user"
)

type Deps struct {
	Container *dig.Container
}

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

func (d *Deps) Init(ctx context.Context, conf *config.RootConfig) error {
	coreFactories := []any{
		func() *config.RootConfig { return conf },
		func() context.Context { return ctx },
		newDB,
		newMgmtClient,
		newAtlassianClient,
		newAtlassianAccountLookupClient,
		newAccountClient,
		newBillingClient,
		newDevOpsClient,
		newLakeClient,
		querysvc.NewService,
		usersvc.NewService,
		syncstatesvc.NewService,
		rolecomputersvc.NewService,
		technicalrolewhitelistsvc.NewService,
		accountresolver.NewService,
		atlassiansyncsvc.NewService,
		eventconsumersvc.NewService,
		reconciliationsvc.NewService,
		services.NewServiceManager,
		queryhdl.NewHandler,
		ingesthdl.NewHandler,
		adminhdl.NewHandler,
		app.NewAPIServer,
	}

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