package task

import (
	"context"

	"github.com/tidbcloud/AgentTeam/internal/store/identity"
	"github.com/tidbcloud/AgentTeam/internal/store/message"
	"github.com/tidbcloud/AgentTeam/internal/store/taskboard"
	"github.com/tidbcloud/AgentTeam/internal/unread"
)

// MessageFanout emits committed visible task messages through the canonical
// browser and daemon fanout path, including outbox delivery marking.
type MessageFanout interface {
	EmitCommittedMessage(ctx context.Context, workspaceID string, appMessage message.AppMessage, delivery message.MessageDelivery)
}

// TaskUnreadRuntime owns owner-local task conversation unread serving state.
// Task overlays aggregate targeted messages, targeted typed activities, and
// manual unread in the same Task conversation.
type TaskUnreadRuntime interface {
	ScopeStates(workspaceID string, memberID string, scopeIDs []string) map[string]unread.ScopeUnreadState
	ApplyReadCursor(event unread.ReadCursorAdvanced) error
	ApplyActivityReadCursor(event unread.ActivityReadCursorAdvanced) error
	ApplyScopeInvalidated(event unread.ScopeInvalidated) error
}

// TaskConversationReadProjection describes the post-commit self projection
// emitted after Task detail advances its durable read cursors.
type TaskConversationReadProjection struct {
	WorkspaceID         string
	UserID              string
	MemberID            string
	TaskID              string
	ScopeID             string
	LastMessageReadSeq  int64
	LastActivityReadSeq int64
}

// TaskConversationReadProjector keeps the unified Inbox conversation and
// cross-tab stream in sync with a Task detail mark-read action.
type TaskConversationReadProjector interface {
	ProjectTaskConversationRead(ctx context.Context, projection TaskConversationReadProjection) error
}

type TaskConversationPolicyProjection struct {
	WorkspaceID string
	UserID      string
	MemberID    string
	TaskID      string
	ScopeID     string
	State       string
}

// TaskConversationPolicyProjector publishes Task Watch changes through the
// member-local conversation stream without creating a second notification
// model.
type TaskConversationPolicyProjector interface {
	ProjectTaskConversationPolicy(ctx context.Context, projection TaskConversationPolicyProjection) error
}

type TaskCollaboratorBoard interface {
	ListTaskCollaborators(ctx context.Context, request taskboard.ListTaskCollaboratorsRequest) (taskboard.ListTaskCollaboratorsResponse, error)
	ListAgentCollaborators(ctx context.Context, request taskboard.ListAgentCollaboratorsRequest) (taskboard.ListAgentCollaboratorsResponse, error)
	AddTaskCollaborator(ctx context.Context, request taskboard.AddTaskCollaboratorRequest) (taskboard.AddTaskCollaboratorResponse, error)
	RemoveTaskCollaborator(ctx context.Context, request taskboard.RemoveTaskCollaboratorRequest) (taskboard.RemoveTaskCollaboratorResponse, error)
	LeaveTaskCollaborator(ctx context.Context, request taskboard.LeaveTaskCollaboratorRequest) (taskboard.LeaveTaskCollaboratorResponse, error)
	ListEffectiveTaskCollaborators(ctx context.Context, request taskboard.ListEffectiveTaskCollaboratorsRequest) (taskboard.ListEffectiveTaskCollaboratorsResponse, error)
	ResolvePrivateAgentContextState(ctx context.Context, request taskboard.ResolvePrivateAgentContextStateRequest) (taskboard.ResolvePrivateAgentContextStateResponse, error)
	ResolvePrivateAgentContextContributionCapability(ctx context.Context, request taskboard.ResolvePrivateAgentContextContributionCapabilityRequest) (taskboard.ResolvePrivateAgentContextContributionCapabilityResponse, error)
	ListPrivateAgentMentionCandidates(ctx context.Context, request taskboard.ListPrivateAgentMentionCandidatesRequest) (taskboard.ListPrivateAgentMentionCandidatesResponse, error)
}

func taskCollaboratorBoard(store *taskboard.Store) TaskCollaboratorBoard {
	if store == nil {
		return nil
	}
	return store
}

type TaskParityBoard interface {
	GetTaskDetail(ctx context.Context, request taskboard.GetTaskDetailRequest) (taskboard.GetTaskDetailResponse, error)
	GetReadableTaskScope(ctx context.Context, request taskboard.GetReadableTaskScopeRequest) (taskboard.GetReadableTaskScopeResponse, error)
	GetTaskTimeline(ctx context.Context, request taskboard.GetTaskTimelineRequest) (taskboard.GetTaskTimelineResponse, error)
	UpdateTask(ctx context.Context, request taskboard.UpdateTaskRequest) (taskboard.UpdateTaskResponse, error)
}

type TaskParityStore interface {
	SendMessageForUserWithMetadata(ctx context.Context, user identity.User, workspaceID string, scopeID string, content string, attachmentIDs []string, metadata map[string]any) (message.AppMessage, message.MessageDelivery, error)

	GetChannelNotificationPanelForUser(ctx context.Context, userID string, workspaceID string, channelID string, agentCursor string, agentLimit int) (message.ScopeNotificationPanel, error)
	SetChannelNotificationSelfStateForUser(ctx context.Context, userID string, workspaceID string, channelID string, state string) (message.ScopeNotificationPanel, error)
	SetChannelNotificationAgentWakeStateForUser(ctx context.Context, userID string, workspaceID string, channelID string, agentID string, state string) (message.ScopeNotificationPanel, error)

	GetThreadNotificationPanelForUser(ctx context.Context, userID string, workspaceID string, threadChannelID string, agentCursor string, agentLimit int) (message.ScopeNotificationPanel, error)
	SetThreadNotificationSelfStateForUser(ctx context.Context, userID string, workspaceID string, threadChannelID string, state string) (message.ScopeNotificationPanel, error)
	SetThreadNotificationAgentWakeStateForUser(ctx context.Context, userID string, workspaceID string, threadChannelID string, agentID string, state string) (message.ScopeNotificationPanel, error)

	GetTaskNotificationPanelForUser(ctx context.Context, userID string, workspaceID string, taskScopeID string) (message.ScopeNotificationPanel, error)
	SetTaskNotificationSelfStateForUser(ctx context.Context, userID string, workspaceID string, taskScopeID string, state string) (message.ScopeNotificationPanel, error)
	SetTaskNotificationAgentWakeStateForUser(ctx context.Context, userID string, workspaceID string, taskScopeID string, agentID string, state string) (message.ScopeNotificationPanel, error)
	SetTaskNotificationAgentsWakeStateForUser(ctx context.Context, userID string, workspaceID string, taskScopeID string, state string) (message.ScopeNotificationPanel, error)
	GetTaskWatchersForUser(ctx context.Context, userID string, workspaceID string, taskScopeID string, cursor string, limit int) (message.TaskWatcherPage, error)

	RequireTaskActiveTargetAgentForUser(ctx context.Context, userID string, workspaceID string, taskScopeID string, agentID string) error
	SetTaskActiveTargetForUser(ctx context.Context, userID string, workspaceID string, target message.TaskActiveTargetRecord) (message.TaskActiveTargetRecord, error)
	ListTaskActiveTargetsForUser(ctx context.Context, userID string, workspaceID string, taskIDs []string) ([]message.TaskActiveTargetRecord, error)
	ClearTaskActiveTargetForUser(ctx context.Context, userID string, workspaceID string, scope string, targetKey string) error
}
