package deps

import (
	"github.com/tidbcloud/devops/pkg/controller"
	aiopsctrl "github.com/tidbcloud/devops/pkg/controller/aiops"
	appctrl "github.com/tidbcloud/devops/pkg/controller/application"
	apprctrl "github.com/tidbcloud/devops/pkg/controller/approval"
	auditctrl "github.com/tidbcloud/devops/pkg/controller/audit"
	billingctrl "github.com/tidbcloud/devops/pkg/controller/billing"
	cloudconfigctrl "github.com/tidbcloud/devops/pkg/controller/cloudconfig"
	"github.com/tidbcloud/devops/pkg/controller/cluster"
	configctrl "github.com/tidbcloud/devops/pkg/controller/configcenter"
	depctrl "github.com/tidbcloud/devops/pkg/controller/controlplane"
	dashboardctrl "github.com/tidbcloud/devops/pkg/controller/dashboard"
	featurewlctrl "github.com/tidbcloud/devops/pkg/controller/feature-wl"
	githubctrl "github.com/tidbcloud/devops/pkg/controller/github"
	incidentctrl "github.com/tidbcloud/devops/pkg/controller/incident"
	itokenctrl "github.com/tidbcloud/devops/pkg/controller/itoken"
	jiractrl "github.com/tidbcloud/devops/pkg/controller/jira"
	jmpctrl "github.com/tidbcloud/devops/pkg/controller/jump"
	k8scalendarctrl "github.com/tidbcloud/devops/pkg/controller/k8scalendar"
	k8splanctrl "github.com/tidbcloud/devops/pkg/controller/k8supgradeplan"
	kernelimagectrl "github.com/tidbcloud/devops/pkg/controller/kernelimage"
	msgctrl "github.com/tidbcloud/devops/pkg/controller/message"
	mgmtportal "github.com/tidbcloud/devops/pkg/controller/mgmt-portal"
	monctrl "github.com/tidbcloud/devops/pkg/controller/monitoring"
	o11yctrl "github.com/tidbcloud/devops/pkg/controller/o11y"
	opctrl "github.com/tidbcloud/devops/pkg/controller/operation"
	premiumupgradectrl "github.com/tidbcloud/devops/pkg/controller/premiumupgrade"
	privctrl "github.com/tidbcloud/devops/pkg/controller/privilege"
	projectctrl "github.com/tidbcloud/devops/pkg/controller/project"
	regionctrl "github.com/tidbcloud/devops/pkg/controller/region"
	releasectrl "github.com/tidbcloud/devops/pkg/controller/release"
	rtctrl "github.com/tidbcloud/devops/pkg/controller/remediationticket"
	tenantctrl "github.com/tidbcloud/devops/pkg/controller/tenant"
	tidbtoolsctrl "github.com/tidbcloud/devops/pkg/controller/tidbtools"
	userctrl "github.com/tidbcloud/devops/pkg/controller/user"
	ubctrl "github.com/tidbcloud/devops/pkg/controller/userbehavior"
	webhookctrl "github.com/tidbcloud/devops/pkg/controller/webhook"
	"github.com/tidbcloud/devops/pkg/infra/asset"
	"github.com/tidbcloud/devops/pkg/infra/clients/aliyuncli"
	"github.com/tidbcloud/devops/pkg/infra/clients/authingcli"
	"github.com/tidbcloud/devops/pkg/infra/clients/awscli"
	"github.com/tidbcloud/devops/pkg/infra/clients/byocimagesynccli"
	"github.com/tidbcloud/devops/pkg/infra/clients/dedicatedcli"
	"github.com/tidbcloud/devops/pkg/infra/clients/eecli"
	"github.com/tidbcloud/devops/pkg/infra/clients/fadcli"
	"github.com/tidbcloud/devops/pkg/infra/clients/fidcli"
	"github.com/tidbcloud/devops/pkg/infra/clients/githubcli"
	"github.com/tidbcloud/devops/pkg/infra/clients/googlecli"
	"github.com/tidbcloud/devops/pkg/infra/clients/jiracli"
	"github.com/tidbcloud/devops/pkg/infra/clients/larkcli"
	"github.com/tidbcloud/devops/pkg/infra/clients/llm_cli"
	"github.com/tidbcloud/devops/pkg/infra/clients/onescli"
	"github.com/tidbcloud/devops/pkg/infra/clients/sendgridcli"
	"github.com/tidbcloud/devops/pkg/infra/config"
	"github.com/tidbcloud/devops/pkg/infra/eventbus"
	"github.com/tidbcloud/devops/pkg/service"
	activeemeatenantsvc "github.com/tidbcloud/devops/pkg/service/activeemeatenant"
	applsvc "github.com/tidbcloud/devops/pkg/service/application"
	apprsvc "github.com/tidbcloud/devops/pkg/service/approval"
	auditsvc "github.com/tidbcloud/devops/pkg/service/audit"
	autocreditsvc "github.com/tidbcloud/devops/pkg/service/autocredit"
	cloudconfigsvc "github.com/tidbcloud/devops/pkg/service/cloudconfig"
	"github.com/tidbcloud/devops/pkg/service/clusterctl"
	clustermntsvc "github.com/tidbcloud/devops/pkg/service/clustermaintenance"
	configsvc "github.com/tidbcloud/devops/pkg/service/configcenter"
	deploymentsvc "github.com/tidbcloud/devops/pkg/service/controlplane"
	dashboardsvc "github.com/tidbcloud/devops/pkg/service/dashboard"
	ghsvc "github.com/tidbcloud/devops/pkg/service/github"
	incidentsvc "github.com/tidbcloud/devops/pkg/service/incident"
	itokensvc "github.com/tidbcloud/devops/pkg/service/itoken"
	jirasvc "github.com/tidbcloud/devops/pkg/service/jira"
	jmpsvc "github.com/tidbcloud/devops/pkg/service/jump"
	k8scalendarsvc "github.com/tidbcloud/devops/pkg/service/k8scalendar/service"
	k8sresourcesvc "github.com/tidbcloud/devops/pkg/service/k8sresource"
	"github.com/tidbcloud/devops/pkg/service/k8supgrade/infrainfo"
	"github.com/tidbcloud/devops/pkg/service/k8supgrade/task"
	k8splansvc "github.com/tidbcloud/devops/pkg/service/k8supgradeplan/service"
	kernelimagesvc "github.com/tidbcloud/devops/pkg/service/kernelimage/service"
	msgsvc "github.com/tidbcloud/devops/pkg/service/message"
	mgmtportalsvc "github.com/tidbcloud/devops/pkg/service/mgmtportal"
	monsvc "github.com/tidbcloud/devops/pkg/service/monitoring"
	opsvc "github.com/tidbcloud/devops/pkg/service/operation"
	premiumupgradesvc "github.com/tidbcloud/devops/pkg/service/premiumupgrade/service"
	privsvc "github.com/tidbcloud/devops/pkg/service/privilege"
	projectsvc "github.com/tidbcloud/devops/pkg/service/project"
	releasesvc "github.com/tidbcloud/devops/pkg/service/release"
	rtsvc "github.com/tidbcloud/devops/pkg/service/remediationticket"
	"github.com/tidbcloud/devops/pkg/service/systemmaintenance"
	tenantsvc "github.com/tidbcloud/devops/pkg/service/tenant"
	tidbtoolssvc "github.com/tidbcloud/devops/pkg/service/tidbtools"
	ubsvc "github.com/tidbcloud/devops/pkg/service/userbehavior"

	"github.com/go-logr/logr"
	"go.uber.org/dig"
	logf "sigs.k8s.io/controller-runtime/pkg/log"
)

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 },
		newCron,
		newGormDB,
		newDBProvider,
		eventbus.NewEventBus,
		newSecretSource,
		githubcli.NewGithubClient,
		larkcli.New,
		newCoreSvcCli,
		newOpsCoreClient,
		newOpsCoreUserClient,
		newAccountSvcCli,
		newBillingSvcCli,
		newMgmtHTTPCli,
		newServerlessSvcCli,
		awscli.NewAWSClient,
		googlecli.NewGoogleClient,
		dedicatedcli.NewInfraAPIClientFromSecret,
		newConfigCenterCli,
		newDataflowCli,
		newGithubActionClient,
		fidcli.NewClient,
		byocimagesynccli.NewClient,
		newClinicCli,
		sendgridcli.NewClient,
		fadcli.NewClient,
		newAIOpsServerCli,
		newO11yCli,
		jiracli.NewJiraClient,
		newMetaDBClient,
		newOnCallCli,
		llm_cli.NewLLMCli,
		asset.NewAsset,
		eecli.NewClient,
		aliyuncli.NewAliyunClient,
		authingcli.NewAuthingClient,
		onescli.NewOnesClient,
	}

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

	services := []any{
		activeemeatenantsvc.NewService,
		autocreditsvc.NewService,
		deploymentsvc.NewService,
		releasesvc.NewService,
		apprsvc.NewService,
		applsvc.NewService,
		auditsvc.NewService,
		clusterctl.NewService,
		incidentsvc.NewService,
		clustermntsvc.NewService,
		systemmaintenance.NewService,
		monsvc.NewService,
		tenantsvc.NewService,
		projectsvc.NewService,
		dashboardsvc.NewService,
		ghsvc.NewService,
		opsvc.NewService,
		configsvc.NewService,
		jmpsvc.NewService,
		jirasvc.NewService,
		cloudconfigsvc.NewService,
		premiumupgradesvc.NewService,
		infrainfo.NewService,
		ubsvc.NewService,
		task.NewService,
		k8scalendarsvc.NewService,
		k8splansvc.NewService,
		rtsvc.NewService,
		msgsvc.NewService,
		privsvc.NewService,
		mgmtportalsvc.NewService,
		k8sresourcesvc.NewService,
		tidbtoolssvc.NewService,
		kernelimagesvc.NewService,
	}
	for _, f := range services {
		if err := d.Container.Provide(f); err != nil {
			return err
		}
	}
	if err := d.Container.Provide(itokensvc.NewService); err != nil {
		return err
	}
	if err := d.Container.Provide(service.NewManager); err != nil {
		return err
	}

	controllers := []any{
		appctrl.NewApplicationController,
		releasectrl.NewReleaseController,
		auditctrl.NewAuditController,
		cluster.NewClusterController,
		incidentctrl.NewIncidentController,
		monctrl.NewMonitoringController,
		webhookctrl.NewWebhookController,
		tenantctrl.NewTenantController,
		githubctrl.NewGithubController,
		dashboardctrl.NewDashboardController,
		opctrl.NewOperationController,
		jmpctrl.NewJumpController,
		apprctrl.NewApprovalController,
		configctrl.NewConfigCenterController,
		cloudconfigctrl.NewCloudConfigController,
		premiumupgradectrl.NewController,
		billingctrl.NewBillingController,
		ubctrl.NewUserBehaviorController,
		rtctrl.NewRemediationTicketController,
		msgctrl.NewMessageController,
		privctrl.NewPrivilegeController,
		mgmtportal.NewMgmtPortalController,
		o11yctrl.NewO11yController,
		aiopsctrl.NewAIOpsController,
		projectctrl.NewProjectController,
		jiractrl.NewJiraController,
		regionctrl.NewRegionController,
		depctrl.NewDeploymentController,
		tidbtoolsctrl.NewTidbToolsController,
		itokenctrl.NewController,
		userctrl.NewAuthController,
		featurewlctrl.NewFeatureWhitelistController,
		k8scalendarctrl.NewController,
		k8splanctrl.NewController,
		kernelimagectrl.NewController,
	}
	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
	}

	if err := d.Container.Provide(controller.NewGrpcServer); err != nil {
		return err
	}

	return nil
}
