package dto

import "time"

// MessageReaction is the realtime/browser payload for one concrete reaction row.
type MessageReaction struct {
	ID            string         `json:"id"`
	Emoji         string         `json:"emoji"`
	AuthorProfile *AuthorProfile `json:"authorProfile"`
	CreatedAt     time.Time      `json:"createdAt"`
}

// MessageParticipationStats summarizes a bounded message page by author family.
type MessageParticipationStats struct {
	Total int64 `json:"total"`
	Agent int64 `json:"agent"`
	Human int64 `json:"human"`
}

// AppMessagePage is the browser-facing channel message page response.
type AppMessagePage struct {
	Messages                              []AppMessage                  `json:"messages"`
	ReplyThreadSummaries                  map[string]ReplyThreadSummary `json:"replyThreadSummaries,omitempty"`
	ParticipationStats                    *MessageParticipationStats    `json:"participationStats,omitempty"`
	HasMore                               bool                          `json:"hasMore"`
	NextCursor                            int64                         `json:"nextCursor,omitempty"`
	HistoryLimited                        bool                          `json:"historyLimited,omitempty"`
	OwnerContextDismissedThroughGlobalSeq int64                         `json:"ownerContextDismissedThroughGlobalSeq,omitempty"`
}

// HistoryPage is the daemon-compatible agent history response body.
type HistoryPage struct {
	Messages            []HistoryMessage `json:"messages"`
	HasMore             bool             `json:"has_more"`
	HistoryLimited      bool             `json:"historyLimited"`
	HistoryLimitMessage string           `json:"historyLimitMessage"`
	LastReadSeq         int64            `json:"last_read_seq"`
}

// MessageSearchResult is the browser-facing message search response.
type MessageSearchResult struct {
	Messages   []AppMessage `json:"messages"`
	TotalCount int          `json:"totalCount"`
	HasMore    bool         `json:"hasMore,omitempty"`
	NextCursor string       `json:"nextCursor,omitempty"`
}

// MessageSearchCursor is the opaque browser search cursor payload.
type MessageSearchCursor struct {
	Rank      int    `json:"rank,omitempty"`
	GlobalSeq int64  `json:"globalSeq,omitempty"`
	ScopeID   string `json:"scopeId,omitempty"`
	Seq       int64  `json:"seq,omitempty"`
	MessageID string `json:"messageId,omitempty"`
}

// MessagePinState is the current viewer's row-level pin state for one message.
type MessagePinState struct {
	IsPinned         bool       `json:"isPinned"`
	PinID            string     `json:"pinId,omitempty"`
	PinnedAt         *time.Time `json:"pinnedAt,omitempty"`
	PinnedByMemberID string     `json:"pinnedByMemberId,omitempty"`
}

// MessagePin is the browser-facing view of one shared pinned message plus the
// current viewer's per-pin state and capabilities.
type MessagePin struct {
	ID                 string                       `json:"id"`
	WorkspaceID        string                       `json:"workspaceId"`
	ScopeID            string                       `json:"scopeId"`
	MessageID          string                       `json:"messageId"`
	PinnedByMemberID   string                       `json:"pinnedByMemberId"`
	PinnedBy           *AuthorProfile               `json:"pinnedBy,omitempty"`
	PinnedAt           time.Time                    `json:"pinnedAt"`
	Message            AppMessage                   `json:"message"`
	ViewerState        MessagePinViewerState        `json:"viewerState"`
	ViewerCapabilities MessagePinViewerCapabilities `json:"viewerCapabilities"`
}

type MessagePinViewerState struct {
}

type MessagePinViewerCapabilities struct {
	CanJump             bool `json:"canJump"`
	CanUnpinForEveryone bool `json:"canUnpinForEveryone"`
}

// MessagePinListResponse is the authoritative pinned-message list state for
// one conversation target from the current viewer's perspective.
type MessagePinListResponse struct {
	ScopeID                string       `json:"scopeId"`
	Pins                   []MessagePin `json:"pins"`
	LatestPin              *MessagePin  `json:"latestPin,omitempty"`
	NextCursor             string       `json:"nextCursor,omitempty"`
	PinRevision            string       `json:"pinRevision,omitempty"`
	ViewerPinStateRevision string       `json:"viewerPinStateRevision,omitempty"`
}

type MessagePinMutationResponse struct {
	Changed bool                   `json:"changed"`
	Pin     *MessagePin            `json:"pin,omitempty"`
	List    MessagePinListResponse `json:"list"`
}

// MessageTopNotice is the browser-facing view of one conversation-level top
// notice plus the current viewer's personal banner state and capabilities.
type MessageTopNotice struct {
	ID                 string                             `json:"id"`
	WorkspaceID        string                             `json:"workspaceId"`
	ScopeID            string                             `json:"scopeId"`
	MessageID          string                             `json:"messageId"`
	SetByMemberID      string                             `json:"setByMemberId"`
	SetBy              *AuthorProfile                     `json:"setBy,omitempty"`
	SetAt              time.Time                          `json:"setAt"`
	Message            AppMessage                         `json:"message"`
	ViewerState        MessageTopNoticeViewerState        `json:"viewerState"`
	ViewerCapabilities MessageTopNoticeViewerCapabilities `json:"viewerCapabilities"`
}

type MessageTopNoticeViewerState struct {
	HiddenFromBannerForMe bool `json:"hiddenFromBannerForMe"`
}

type MessageTopNoticeViewerCapabilities struct {
	CanJump                bool `json:"canJump"`
	CanRemoveForEveryone   bool `json:"canRemoveForEveryone"`
	CanHideFromBannerForMe bool `json:"canHideFromBannerForMe"`
	CanShowInBannerAgain   bool `json:"canShowInBannerAgain"`
}

// MessageTopNoticeResponse is the viewer-local top-message banner state for one
// conversation target. It is intentionally separate from the shared Pins tab.
type MessageTopNoticeResponse struct {
	ScopeID                 string            `json:"scopeId"`
	TopNotice               *MessageTopNotice `json:"topNotice,omitempty"`
	TopNoticeRevision       string            `json:"topNoticeRevision,omitempty"`
	ViewerTopNoticeRevision string            `json:"viewerTopNoticeRevision,omitempty"`
}

type MessageTopNoticeMutationResponse struct {
	Changed   bool                     `json:"changed"`
	TopNotice *MessageTopNotice        `json:"topNotice,omitempty"`
	State     MessageTopNoticeResponse `json:"state"`
}

// MessageDeliveryDiagnostics is the browser-facing delivery diagnostics response.
type MessageDeliveryDiagnostics struct {
	Message                  MessageDeliveryDiagnosticsMessage `json:"message"`
	WakeInferenceBasis       string                            `json:"wakeInferenceBasis"`
	WakeInferenceExplanation string                            `json:"wakeInferenceExplanation"`
	Summary                  MessageDeliveryDiagnosticsSummary `json:"summary"`
	Agents                   []MessageDeliveryDiagnosticsAgent `json:"agents"`
}

type MessageDeliveryDiagnosticsSummary struct {
	TargetedAgentCount      int  `json:"targetedAgentCount"`
	ExcludedAgentCount      int  `json:"excludedAgentCount"`
	WakeDeliverRunningCount int  `json:"wakeDeliverRunningCount"`
	WakeStartCount          int  `json:"wakeStartCount"`
	WakeBlockedCount        int  `json:"wakeBlockedCount"`
	OwnerPrivateRequired    bool `json:"ownerPrivateRequired,omitempty"`
}

type MessageDeliveryDiagnosticsMessage struct {
	ID                      string    `json:"id"`
	ChannelID               string    `json:"channelId"`
	ChannelType             string    `json:"channelType"`
	ParentChannelID         string    `json:"parentChannelId,omitempty"`
	ParentChannelType       string    `json:"parentChannelType,omitempty"`
	MessageType             string    `json:"messageType,omitempty"`
	Content                 string    `json:"content"`
	CreatedAt               time.Time `json:"createdAt"`
	RoutingMode             string    `json:"routingMode"`
	RoutingExplanation      string    `json:"routingExplanation"`
	ContextScope            string    `json:"contextScope"`
	ContextScopeExplanation string    `json:"contextScopeExplanation"`
}

type MessageDeliveryDiagnosticsAgent struct {
	AgentID                 string `json:"agentId"`
	AgentName               string `json:"agentName"`
	MemberID                string `json:"memberId"`
	MachineID               string `json:"machineId"`
	MachineName             string `json:"machineName,omitempty"`
	AgentStatus             string `json:"agentStatus,omitempty"`
	AgentActivity           string `json:"agentActivity,omitempty"`
	AgentActivityDetail     string `json:"agentActivityDetail,omitempty"`
	AutoWakeEnabled         bool   `json:"autoWakeEnabled"`
	SubscriptionState       string `json:"subscriptionState,omitempty"`
	MachineOnline           bool   `json:"machineOnline"`
	ScopeStatus             string `json:"scopeStatus"`
	ScopeExplanation        string `json:"scopeExplanation"`
	DeliveryStatus          string `json:"deliveryStatus"`
	DeliveryReason          string `json:"deliveryReason"`
	DeliveryExplanation     string `json:"deliveryExplanation"`
	ExecutionResult         string `json:"executionResult,omitempty"`
	OwnerPrivateState       string `json:"ownerPrivateState,omitempty"`
	OwnerPrivateExplanation string `json:"ownerPrivateExplanation,omitempty"`
	WakeStatus              string `json:"wakeStatus"`
	WakeExplanation         string `json:"wakeExplanation"`
}

// ChannelMemberSummary is one channel member row for the browser member list.
type ChannelMemberSummary struct {
	ID               string         `json:"id"`
	Name             string         `json:"name"`
	DisplayName      string         `json:"displayName"`
	MemberID         string         `json:"memberId,omitempty"`
	LegacyTargetKeys []string       `json:"legacyTargetKeys,omitempty"`
	AvatarURL        string         `json:"avatarUrl"`
	OwnerProfile     *AuthorProfile `json:"ownerProfile,omitempty"`
	OwnerUserID      string         `json:"ownerUserId,omitempty"`
	Model            string         `json:"model,omitempty"`
	Visibility       string         `json:"visibility,omitempty"`
	CanRemove        bool           `json:"canRemove,omitempty"`
}

// ChannelPrivateAgentSummary is one owner-scoped private agent in a channel member list.
type ChannelPrivateAgentSummary struct {
	ID           string         `json:"id"`
	Name         string         `json:"name"`
	DisplayName  string         `json:"displayName"`
	MemberID     string         `json:"memberId,omitempty"`
	AvatarURL    string         `json:"avatarUrl"`
	Model        string         `json:"model,omitempty"`
	Visibility   string         `json:"visibility,omitempty"`
	OwnerProfile *AuthorProfile `json:"ownerProfile,omitempty"`
	// OwnerMemberID/OwnerUserID/OwnerName/OwnerDisplayName are legacy
	// compatibility aliases. New UI code must derive owner identity from
	// OwnerProfile.
	OwnerMemberID    string `json:"ownerMemberId"`
	OwnerUserID      string `json:"ownerUserId,omitempty"`
	OwnerName        string `json:"ownerName,omitempty"`
	OwnerDisplayName string `json:"ownerDisplayName"`
}

// ChannelMemberList is the browser-facing channel member list response.
type ChannelMemberList struct {
	Agents        []ChannelMemberSummary       `json:"agents"`
	Humans        []ChannelMemberSummary       `json:"humans"`
	Services      []ChannelMemberSummary       `json:"services,omitempty"`
	PrivateAgents []ChannelPrivateAgentSummary `json:"privateAgents,omitempty"`
	TotalCount    int                          `json:"totalCount"`
	HasMore       bool                         `json:"hasMore"`
	NextCursor    string                       `json:"nextCursor"`
}

// ChannelAddablePeopleResponse is a bounded page of non-agent channel member candidates.
type ChannelAddablePeopleResponse struct {
	Humans     []WorkspaceMemberResponse `json:"humans"`
	Services   []AppInstallationResponse `json:"services"`
	HasMore    bool                      `json:"hasMore"`
	NextCursor string                    `json:"nextCursor"`
}

// DMChannel is the browser-facing direct-message channel row.
type DMChannel struct {
	ID              string     `json:"id"`
	PeerType        string     `json:"peerType"`
	PeerID          string     `json:"peerId"`
	PeerName        string     `json:"peerName"`
	PeerDisplayName string     `json:"peerDisplayName,omitempty"`
	PeerAvatarURL   string     `json:"peerAvatarUrl,omitempty"`
	LastMessageAt   *time.Time `json:"lastMessageAt,omitempty"`
	SidebarHidden   bool       `json:"sidebarHidden,omitempty"`
}

// SubscribedThread is one thread inbox/sidebar row.
type SubscribedThread struct {
	ThreadChannelID               string                   `json:"threadChannelId"`
	ParentChannelID               string                   `json:"parentChannelId"`
	ParentChannelType             string                   `json:"parentChannelType"`
	ParentLabel                   string                   `json:"parentLabel"`
	ParentMessageID               string                   `json:"parentMessageId"`
	ParentMessageShortID          string                   `json:"parentMessageShortId"`
	ParentMessagePreview          string                   `json:"parentMessagePreview,omitempty"`
	ParentMessageMetadata         map[string]any           `json:"parentMessageMetadata,omitempty"`
	ParentMessageResolvedMentions []ResolvedMention        `json:"parentMessageResolvedMentions,omitempty"`
	ParentMessageAuthor           string                   `json:"parentMessageAuthor,omitempty"`
	Title                         string                   `json:"title"`
	SubscriptionState             string                   `json:"subscriptionState,omitempty"`
	ParticipantIDs                []string                 `json:"participantIds"`
	Participants                  []ReplyThreadParticipant `json:"participants"`
	ParticipantCount              int                      `json:"participantCount"`
	ReplyAuthorIDs                []string                 `json:"replyAuthorIds"`
	ReplyAuthors                  []ReplyThreadParticipant `json:"replyAuthors"`
	ReplyCount                    int64                    `json:"replyCount"`
	LastReplyAt                   *time.Time               `json:"lastReplyAt,omitempty"`
	LastActivityAt                *time.Time               `json:"lastActivityAt,omitempty"`
}

type ThreadInboxPage struct {
	Threads    []SubscribedThread `json:"threads"`
	HasMore    bool               `json:"hasMore"`
	NextCursor string             `json:"nextCursor,omitempty"`
}

type ThreadInboxCount struct {
	Count int64 `json:"count"`
}

type ThreadMembership struct {
	ThreadChannelID   string `json:"threadChannelId,omitempty"`
	Subscribed        bool   `json:"subscribed"`
	SubscriptionState string `json:"subscriptionState,omitempty"`
}

// ChannelShareCardView is the browser-facing channel share card state.
type ChannelShareCardView struct {
	MessageID     string `json:"messageId"`
	CardID        string `json:"cardId"`
	CardChannelID string `json:"cardChannelId"`
	ChannelID     string `json:"channelId"`
	Name          string `json:"name"`
	Description   string `json:"description"`
	Visibility    string `json:"visibility,omitempty"`
	Status        string `json:"status"`
	Joined        bool   `json:"joined"`
	CanJoin       bool   `json:"canJoin"`
	CanOpen       bool   `json:"canOpen"`
	CanRevoke     bool   `json:"canRevoke"`
	Revoked       bool   `json:"revoked"`
	RevokedAt     string `json:"revokedAt,omitempty"`
}

// ThreadShareSnapshotMessage is a minimal immutable message copy in a thread share card.
type ThreadShareSnapshotMessage struct {
	ID         string `json:"id"`
	AuthorName string `json:"authorName"`
	Content    string `json:"content"`
	CreatedAt  string `json:"createdAt"`
}

// ThreadShareCardView is the browser-facing immutable reply-thread share card state.
type ThreadShareCardView struct {
	MessageID                  string                       `json:"messageId"`
	SourceParentChannelID      string                       `json:"sourceParentChannelId"`
	SourceParentMessageID      string                       `json:"sourceParentMessageId,omitempty"`
	SourceParentMessageShortID string                       `json:"sourceParentMessageShortId"`
	SourceLabel                string                       `json:"sourceLabel"`
	Title                      string                       `json:"title"`
	Preview                    string                       `json:"preview"`
	MessageCount               int                          `json:"messageCount"`
	ParticipantCount           int                          `json:"participantCount"`
	CanOpenSource              bool                         `json:"canOpenSource"`
	Messages                   []ThreadShareSnapshotMessage `json:"messages"`
}
