package testkit

import (
	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/auth"
	apifanout "github.com/tidbcloud/AgentTeam/internal/api/im/fanout"
	"github.com/tidbcloud/AgentTeam/internal/service/authflow"
	"github.com/tidbcloud/AgentTeam/internal/service/workspace"
	"github.com/tidbcloud/AgentTeam/internal/store/app"
	"github.com/tidbcloud/AgentTeam/internal/store/identity"
)

func runtimeAppStore(runtime *Runtime) *app.Store {
	if runtime == nil {
		return nil
	}
	return runtime.Store.App()
}

func runtimeIdentity(runtime *Runtime) *identity.Store {
	if runtime == nil {
		return nil
	}
	return runtime.Store.Identity()
}

func runtimeAuthFlow(runtime *Runtime) auth.AuthFlow {
	if runtime == nil {
		return nil
	}
	return authflow.New(authflow.Dependencies{
		RegistrationAllowlist: runtimeIdentity(runtime),
		WorkspaceInvites:      runtime.Store.App(),
		Organizations:         runtime.Organizations,
	})
}

func runtimeAppSessionAuth(runtime *Runtime) api.SessionAuthenticator {
	if runtime == nil {
		return nil
	}
	return runtimeIdentity(runtime)
}

func runtimeAppWorkspaceStore(runtime *Runtime) api.WorkspaceResolver {
	if runtime == nil || runtime.Store == nil {
		return nil
	}
	return runtime.Store.Workspace()
}

func runtimeWorkspaceFlow(runtime *Runtime) *workspace.Service {
	if runtime == nil || runtime.Store == nil {
		return nil
	}
	return workspace.New(workspace.Dependencies{
		Workspaces:      runtime.Store.Workspace(),
		WorkspaceAdmin:  runtime.Store.App(),
		Machines:        runtime.Store.App(),
		MachineTokens:   runtime.Store.Agent(),
		MiniappPairings: runtime.Store.Identity(),
	})
}

func runtimeDeliveryFanout(runtime *Runtime) apifanout.DeliveryFanout {
	if runtime == nil {
		return apifanout.DeliveryFanout{}
	}
	var notifier apifanout.AgentNotifier
	if runtime.Hub != nil {
		notifier = runtime.Hub
	}
	var streamWriter apifanout.StreamEventWriter
	if runtime.Store != nil {
		streamWriter = runtime.Store.IM()
	}
	fanout := apifanout.NewDeliveryFanout(notifier, streamWriter, runtime.Logger).
		WithScopeFanoutMarker(runtime.Store.App()).
		WithTaskScopeLifecycleGuard(runtime.Store.Message())
	if runtime.UnreadRuntime != nil {
		fanout = fanout.WithUnreadRuntime(runtime.UnreadRuntime).WithUnreadDeltaSink(runtime.LiveEmitter)
	}
	if messageStore := runtime.Store.Message(); messageStore != nil {
		fanout = fanout.WithReplyThreadRootPreloader(apifanout.NewScopeReplyThreadRootPreloader(messageStore))
	}
	return fanout
}
