package deps

import (
	"context"

	"github.com/tidbcloud/aisupport/services/ticket-manager/config"
	"github.com/tidbcloud/aisupport/services/ticket-manager/internal/app"
	agenthdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/agent"
	collabhdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/collaboration"
	dispatchhdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/dispatch"
	enghdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/engineer"
	larkhdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/lark"
	taskhdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/task"
	tkthdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/ticket"
	workspacehdl "github.com/tidbcloud/aisupport/services/ticket-manager/internal/app/handlers/workspace"
	"github.com/tidbcloud/aisupport/services/ticket-manager/internal/services"
	agentsvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/agent"
	collabsvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/collaboration"
	dispatchsvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/dispatch"
	engsvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/engineer"
	ingestsvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/ingest"
	tasksvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/task"
	ticketsvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/ticket"
	workspacesvc "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/workspace"

	"go.uber.org/dig"
)

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,
	}

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

	cliFactories := []any{
		newJiraClient,
		newLarkClient,
		newLarkEventDispatcher,
		newLarkCardDispatcher,
		newLarkLoginDispatcher,
		newAgentGatewayClient,
		newCoreClient,
		newDevOpsClient,
		newOncallClient,
	}
	for _, f := range cliFactories {
		if err := d.Container.Provide(f); err != nil {
			return err
		}
	}

	svcFactories := []any{
		engsvc.NewService,
		dispatchsvc.NewService,
		tasksvc.NewService,
		ticketsvc.NewService,
		ingestsvc.NewService,
		collabsvc.NewService,
		workspacesvc.NewService,
		agentsvc.NewService,
	}
	for _, f := range svcFactories {
		if err := d.Container.Provide(f); err != nil {
			return err
		}
	}
	if err := d.Container.Provide(services.NewServiceManager); err != nil {
		return err
	}

	handlerFactries := []any{
		agenthdl.NewHandler,
		collabhdl.NewHandler,
		taskhdl.NewHandler,
		tkthdl.NewTicketsHandler,
		workspacehdl.NewHandler,
		larkhdl.NewLarkHandler,
		enghdl.NewEngineerHandler,
		dispatchhdl.NewHandler,
	}
	for _, f := range handlerFactries {
		if err := d.Container.Provide(f); err != nil {
			return err
		}
	}
	if err := d.Container.Provide(app.NewAPIServer); err != nil {
		return err
	}

	return nil
}
