package workspace

import (
	"context"
	"encoding/json"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/runtimecontrol"
	workspaceservice "github.com/tidbcloud/AgentTeam/internal/service/workspace"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
	"github.com/tidbcloud/AgentTeam/internal/store/app/runtime"
	"github.com/tidbcloud/AgentTeam/internal/store/identity"
	"github.com/tidbcloud/AgentTeam/internal/store/organization"
	"github.com/tidbcloud/AgentTeam/internal/store/plan"
	"github.com/tidbcloud/AgentTeam/internal/store/workspace"
)

// SessionStore is the authentication surface needed by workspace routes.
type SessionStore interface {
	AuthenticateSession(ctx context.Context, token string) (identity.AuthenticatedUser, error)
}

// WorkspaceService is the workspace administration surface used by workspace,
// member, and machine routes. *workspaceflow.Service satisfies this interface.
type WorkspaceService interface {
	CreateMachineConnectToken(ctx context.Context, userID string, workspaceID string, machineID string, serverURL string) (string, error)
	CreateMachineForWorkspace(ctx context.Context, userID string, workspaceID string, name string) (workspaceservice.Machine, string, error)
	CreateMiniappPairingCode(ctx context.Context, userID string, workspaceID string, serverURL string) (workspaceservice.MiniappPairingIssueResult, error)
	CreateWorkspaceInvite(ctx context.Context, inviterUserID string, workspaceID string, email string, tokenHash string, expiresAt time.Time) (string, error)
	CreateWorkspaceMobileInvite(ctx context.Context, inviterUserID string, workspaceID string, mobile string, tokenHash string, expiresAt time.Time) (string, error)
	DeleteMachineForWorkspace(ctx context.Context, userID string, workspaceID string, machineID string) error
	EvictMachineForWorkspace(ctx context.Context, userID string, workspaceID string, machineID string) ([]string, error)
	ExchangeMachineConnectToken(ctx context.Context, token string) (workspaceservice.MachineConnectExchangeResult, error)
	ResolveMachineAuth(ctx context.Context, apiKey string, serverURL string) (workspaceservice.MachineConnectExchangeResult, error)
	AccountBehaviorSettingsForUser(ctx context.Context, userID string) (workspaceservice.AccountBehaviorSettings, error)
	GetChannelSidebarPreferenceForUser(ctx context.Context, userID string, workspaceID string) (workspaceservice.ChannelSidebarPreference, bool, error)
	GetWorkspaceForUser(ctx context.Context, userID string, workspaceID string) (workspace.Summary, error)
	ListAgentsForWorkspace(ctx context.Context, userID string, workspaceID string) ([]agent.AppAgent, error)
	ListAgentsForMachineWorkspace(ctx context.Context, userID string, workspaceID string, machineID string) ([]agent.AppAgent, error)
	ListAllMachinesForWorkspace(ctx context.Context, userID string, workspaceID string) ([]workspaceservice.Machine, error)
	ListAllMachinesForWorkspacePage(ctx context.Context, userID string, workspaceID string, options workspaceservice.MachineListOptions) (workspaceservice.MachineListPage, error)
	ListOwnMachinesForWorkspace(ctx context.Context, userID string, workspaceID string) ([]workspaceservice.Machine, error)
	ListOwnMachinesForWorkspacePage(ctx context.Context, userID string, workspaceID string, options workspaceservice.MachineListOptions) (workspaceservice.MachineListPage, error)
	ListWorkspaceInvitesForUser(ctx context.Context, userID string, workspaceID string) ([]workspace.WorkspaceInvite, error)
	ListWorkspaceMembersForUserPage(ctx context.Context, userID string, workspaceID string, options workspace.WorkspaceMemberListOptions) (workspace.WorkspaceMemberPage, error)
	GetWorkspaceMemberForUser(ctx context.Context, actorUserID string, workspaceID string, memberID string) (workspace.WorkspaceMember, error)
	LookupWorkspaceMembersForUser(ctx context.Context, actorUserID string, workspaceID string, options workspace.WorkspaceMemberLookupOptions) ([]workspace.WorkspaceMember, error)
	RequireWorkspaceMemberManagementForUser(ctx context.Context, actorUserID string, workspaceID string) error
	WorkspaceMemberOffboardingImpactForUser(ctx context.Context, actorUserID string, workspaceID string, targetUserID string) (workspace.WorkspaceMemberOffboardingImpact, error)
	ListUserWorkspaces(ctx context.Context, userID string) ([]workspace.Summary, error)
	LoadWorkspaceUsageForUser(ctx context.Context, userID string, workspaceID string) (workspace.WorkspaceUsage, error)
	RenameMachineForWorkspace(ctx context.Context, userID string, workspaceID string, machineID string, name string) error
	RequireMachineManagementForUser(ctx context.Context, userID string, workspaceID string, machineID string) error
	RevokeWorkspaceInviteForUser(ctx context.Context, userID string, workspaceID string, inviteID string) error
	RotateMachineKeyForUser(ctx context.Context, userID string, workspaceID string, machineID string) (string, error)
	UpdateAccountBehaviorSettingsForUser(ctx context.Context, userID string, update workspaceservice.AccountBehaviorSettingsUpdate) (workspaceservice.AccountBehaviorSettings, error)
	PutChannelSidebarPreferenceForUser(ctx context.Context, userID string, workspaceID string, state workspaceservice.ChannelSidebarPreferenceState, expectedRevision *int64) (workspaceservice.ChannelSidebarPreference, error)
	UpdateWorkspaceNameForUser(ctx context.Context, userID string, workspaceID string, name string) (workspace.Summary, error)
	RemoveWorkspaceMemberForUser(ctx context.Context, actorUserID string, workspaceID string, targetUserID string) ([]string, error)
	UpdateWorkspaceMemberRoleForUser(ctx context.Context, actorUserID string, workspaceID string, targetUserID string, role string) error
}

// OrganizationProvider is the organization subset used to annotate workspace-member access.
type OrganizationProvider interface {
	CreateOrganizationWorkspaceForUser(ctx context.Context, userID string, organizationID string, name string, slug string) (organization.OrganizationWorkspaceView, error)
	GetHostedModelSelectionForWorkspace(ctx context.Context, organizationID string, workspaceID string) (organization.OrganizationHostedModelSelectionView, error)
	GetWorkspaceOrganizationForUser(ctx context.Context, userID string, workspaceID string) (organization.OrganizationSummary, error)
	ListWorkspaceMemberAccessSources(ctx context.Context, workspaceID string) ([]organization.WorkspaceMemberAccessSourceView, error)
	ListWorkspaceMemberAccessSourcesForUsers(ctx context.Context, workspaceID string, userIDs []string) ([]organization.WorkspaceMemberAccessSourceView, error)
	ListVisibleOrganizationProvidersForWorkspace(ctx context.Context, workspaceID string) ([]organization.OrganizationProviderView, error)
}

// MachineRuntime is the daemon hub subset used by machine administration routes.
type MachineRuntime interface {
	AgentRuntimeRunning(machineID string, agentID string) bool
	DeleteMachineWorkspaceDirectory(ctx context.Context, machineID string, directoryName string) (bool, error)
	DisconnectMachine(machineID string)
	MachineConnected(machineID string) bool
	MachineDashboardSupported(machineID string) bool
	MachineDirectoryBrowseSupported(machineID string) bool
	MachineRuntimeCatalog(machineID string) ([]string, map[string]runtime.RuntimeDefaults, bool)
	QueryMachineDashboard(ctx context.Context, machineID string, request runtimecontrol.MachineDashboardRequest) (runtimecontrol.MachineDashboardResponse, error)
	ScanMachineWorkspace(ctx context.Context, machineID string) ([]agent.WorkspaceDirectory, error)
	ScanMachineWorkspacePage(ctx context.Context, machineID string, opts agent.WorkspaceListOptions) (agent.WorkspaceDirectoryPage, error)
	ListMachineDirectoriesPage(ctx context.Context, machineID string, path string, opts agent.WorkspaceListOptions) (agent.MachineDirectoryPage, error)
	RestartAgent(ctx context.Context, machineID string, agentID string) error
	SyncMachineCatalog(ctx context.Context, machineID string) error

	// Machine Detail tab remotes. Each method routes one request to the
	// connected daemon's matching remote endpoint; the response is opaque
	// JSON sourced from the daemon (the daemon owns the desktop-local
	// schema for settings, runtimes, and MCP server config).
	QueryMachineSettings(ctx context.Context, workspaceID string, machineID string) (json.RawMessage, error)
	UpdateMachineSettings(ctx context.Context, workspaceID string, machineID string, desktop json.RawMessage) (json.RawMessage, error)
	QueryMachineRuntimesBundle(ctx context.Context, workspaceID string, machineID string) (json.RawMessage, error)
	QueryMachineRuntimeConfig(ctx context.Context, workspaceID string, machineID string, name string) (json.RawMessage, error)
	UpdateMachineRuntimeConfig(ctx context.Context, workspaceID string, machineID string, name string, config json.RawMessage) (json.RawMessage, error)
	ValidateMachineRuntimeConfig(ctx context.Context, workspaceID string, machineID string, name string, config json.RawMessage) (json.RawMessage, error)
	DetectMachineRuntimes(ctx context.Context, workspaceID string, machineID string) (json.RawMessage, error)
	QueryMachineMCPServers(ctx context.Context, workspaceID string, machineID string) (json.RawMessage, error)
	UpsertMachineMCPServer(ctx context.Context, workspaceID string, machineID string, server json.RawMessage) (json.RawMessage, error)
	DeleteMachineMCPServer(ctx context.Context, workspaceID string, machineID string, name string) (json.RawMessage, error)
	TestMachineMCPServer(ctx context.Context, workspaceID string, machineID string, name string) (json.RawMessage, error)
}

// WorkspaceRealtime is the realtime side effect surface for workspace admin actions.
type WorkspaceRealtime interface {
	EmitWorkspaceMembersUpdated(workspaceID string)
	EmitWorkspaceMemberRoleUpdated(workspaceID string, userID string, role string)
	// DisconnectWorkspaceUser forcibly closes every active /events/stream
	// connection owned by (workspaceID, userID). Mirrors the old Socket.IO
	// SocketsDisconnect-by-user-room call used when membership is revoked.
	DisconnectWorkspaceUser(workspaceID string, userID string)
}

// WorkspaceUnreadReader is the owner-local unread runtime read surface used by
// workspace management responses when this process owns the workspace runtime.
type WorkspaceUnreadReader interface {
	WorkspaceHasUnread(workspaceID string, memberID string) bool
}

// PlanStore is the plan quota read surface used by workspace routes.
type PlanStore interface {
	LoadWorkspaceUsageView(ctx context.Context, workspaceID string, ownerUserID string) (plan.WorkspaceUsageView, error)
}
