package dto

import (
	"encoding/json"
	"time"
)

// AgentSendMessageRequest is the daemon-compatible request body for agent-authored messages.
type AgentSendMessageRequest struct {
	Target           string                          `json:"target"`
	Content          string                          `json:"content"`
	AttachmentIDs    []string                        `json:"attachmentIds"`
	ClientMessageID  string                          `json:"clientMessageId,omitempty"`
	Freshness        *AgentSendMessageFreshnessInput `json:"freshness,omitempty"`
	TeamInvokeTeamID string                          `json:"teamInvokeTeamId,omitempty"`
}

type AgentSendMessageFreshnessInput struct {
	TargetKey        string   `json:"targetKey"`
	SeenUpToSeq      int64    `json:"seenUpToSeq"`
	SourceMessageIDs []string `json:"sourceMessageIds,omitempty"`
}

// AgentResolveChannelRequest resolves a AgentTeam target string to a scope id for one agent.
type AgentResolveChannelRequest struct {
	Target  string `json:"target"`
	Purpose string `json:"purpose,omitempty"`
}

// AgentSendMessageResponse returns the persisted message id.
type AgentSendMessageResponse struct {
	State                string `json:"state,omitempty"`
	MessageID            string `json:"messageId,omitempty"`
	TargetKey            string `json:"targetKey,omitempty"`
	ClientMessageID      string `json:"clientMessageId,omitempty"`
	SeenUpToSeq          int64  `json:"seenUpToSeq,omitempty"`
	AcceptedSeq          int64  `json:"acceptedSeq,omitempty"`
	LatestSeq            int64  `json:"latestSeq,omitempty"`
	NeedsRefreshUntilSeq int64  `json:"needsRefreshUntilSeq,omitempty"`
}

// AgentResolveChannelResponse returns the resolved scope id for a AgentTeam target.
type AgentResolveChannelResponse struct {
	ScopeID   string `json:"scopeId"`
	TargetKey string `json:"targetKey,omitempty"`
}

// MessageReactionReactor is one reactor entry inside a message reaction aggregate.
type MessageReactionReactor struct {
	AuthorProfile *AuthorProfile `json:"authorProfile"`
}

// MessageReactionAggregate is the message-row reaction shape used by history and app reads.
type MessageReactionAggregate struct {
	Emoji    string                   `json:"emoji"`
	Count    int                      `json:"count"`
	Reactors []MessageReactionReactor `json:"reactors,omitempty"`
}

// AuthorProfile is the canonical browser-facing author identity. Browser/API/socket
// message rows carry this profile directly; old daemon wire adapters derive their
// retained compatibility fields at the daemon boundary.
type AuthorProfile struct {
	ActorType      string `json:"actorType"`
	PrincipalID    string `json:"principalId,omitempty"`
	MemberID       string `json:"memberId,omitempty"`
	TargetID       string `json:"targetId,omitempty"`
	DisplayName    string `json:"displayName"`
	AvatarURL      string `json:"avatarUrl,omitempty"`
	ServiceKind    string `json:"serviceKind,omitempty"`
	ServiceSlug    string `json:"serviceSlug,omitempty"`
	ServiceBuiltin bool   `json:"serviceBuiltin,omitempty"`
	Badge          string `json:"badge,omitempty"`
}

// AppMessageDeliverySummaryPreview is the compact delivery-summary shape attached
// to app message rows when diagnostics are available.
type AppMessageDeliverySummaryPreview struct {
	TargetedAgentCount int `json:"targetedAgentCount"`
	ExcludedAgentCount int `json:"excludedAgentCount"`
	ActiveNowCount     int `json:"activeNowCount"`
}

// ResolvedMention is a display annotation for one raw @token in message content.
type ResolvedMention struct {
	Token         string `json:"token"`
	Type          string `json:"type"`
	ID            string `json:"id"`
	DisplayName   string `json:"displayName"`
	ResolvedToken string `json:"canonicalToken,omitempty"`
}

// ContributionSource is the typed source/run explanation for one visible contribution.
type ContributionSource struct {
	Kind      string `json:"kind,omitempty"`
	RefType   string `json:"refType,omitempty"`
	RefID     string `json:"refId,omitempty"`
	RunID     string `json:"runId,omitempty"`
	EventID   string `json:"eventId,omitempty"`
	EventType string `json:"eventType,omitempty"`
	Label     string `json:"label,omitempty"`
}

// ReceiveMessage is the API wire message shape for daemon delivery payloads.
type ReceiveMessage struct {
	MessageID                string                  `json:"message_id,omitempty"`
	TargetKey                string                  `json:"target_key,omitempty"`
	TargetSeq                int64                   `json:"target_seq,omitempty"`
	InterruptPolicy          string                  `json:"interruptPolicy,omitempty"`
	ChannelType              string                  `json:"channel_type"`
	ChannelName              string                  `json:"channel_name"`
	ChannelDisplayName       string                  `json:"channel_display_name,omitempty"`
	ParentChannelType        string                  `json:"parent_channel_type,omitempty"`
	ParentChannelName        string                  `json:"parent_channel_name,omitempty"`
	ParentChannelDisplayName string                  `json:"parent_channel_display_name,omitempty"`
	SenderType               string                  `json:"sender_type"`
	SenderName               string                  `json:"sender_name"`
	AuthorProfile            *AuthorProfile          `json:"author_profile,omitempty"`
	MessageType              string                  `json:"message_type,omitempty"`
	Source                   *ContributionSource     `json:"source,omitempty"`
	Content                  string                  `json:"content"`
	Metadata                 map[string]any          `json:"metadata,omitempty"`
	Timestamp                time.Time               `json:"timestamp"`
	Attachments              []AppAttachment         `json:"attachments,omitempty"`
	ActiveTaskTarget         ReceiveActiveTaskTarget `json:"activeTaskTarget,omitempty,omitzero"`
	TeamContexts             []ReceiveTeamContext    `json:"teamContexts,omitempty"`
}

// ReceiveActiveTaskTarget is the active-task routing hint delivered to agent runtimes.
type ReceiveActiveTaskTarget struct {
	Channel        string `json:"channel,omitempty"`
	TaskNumber     int64  `json:"taskNumber,omitempty"`
	Source         string `json:"source,omitempty"`
	ThreadTarget   string `json:"threadTarget,omitempty"`
	Role           string `json:"role,omitempty"`
	RootTaskNumber int64  `json:"rootTaskNumber,omitempty"`
}

func (target ReceiveActiveTaskTarget) IsZero() bool {
	return target.Channel == "" || target.TaskNumber <= 0
}

// ReceiveTeamContext is the agent-facing Team mention context attached to one
// ReceiveMessage. It deliberately omits internal role version fields.
type ReceiveTeamContext struct {
	TeamID            string                     `json:"teamId"`
	TeamHandle        string                     `json:"teamHandle"`
	TeamDisplayName   string                     `json:"teamDisplayName"`
	TeamDescription   string                     `json:"teamDescription,omitempty"`
	TeamMemberID      string                     `json:"teamMemberId"`
	Role              string                     `json:"role,omitempty"`
	RoleLabel         string                     `json:"roleLabel,omitempty"`
	RoleOverlayPrompt string                     `json:"roleOverlayPrompt,omitempty"`
	MemberRoster      []ReceiveTeamMemberContext `json:"memberRoster"`
	// Workflow marks a Workflow-specific minimal context that must render only
	// the responder's own membership + minimal Team identity (no roster, no
	// ordinary Team invocation copy, no leader responsibility updates).
	Workflow bool `json:"workflow,omitempty"`
}

type ReceiveTeamMemberContext struct {
	TeamMemberID      string `json:"teamMemberId"`
	ActorKind         string `json:"actorKind"`
	ActorID           string `json:"actorId"`
	DisplayName       string `json:"displayName"`
	Handle            string `json:"handle,omitempty"`
	Role              string `json:"role,omitempty"`
	RoleLabel         string `json:"roleLabel,omitempty"`
	RoleOverlayPrompt string `json:"roleOverlayPrompt,omitempty"`
	WakeOnTeamMention bool   `json:"wakeOnTeamMention,omitempty"`
	DeliveryKind      string `json:"deliveryKind"`
	Self              bool   `json:"self,omitempty"`
}

// HistoryMessage is the API wire message shape for agent history/search.
type HistoryMessage struct {
	Seq           int64               `json:"seq"`
	TargetKey     string              `json:"targetKey,omitempty"`
	TargetSeq     int64               `json:"targetSeq,omitempty"`
	ID            string              `json:"id,omitempty"`
	SenderType    string              `json:"senderType"`
	SenderName    string              `json:"senderName"`
	AuthorProfile *AuthorProfile      `json:"authorProfile,omitempty"`
	Source        *ContributionSource `json:"source,omitempty"`
	Content       string              `json:"content"`
	Metadata      map[string]any      `json:"metadata,omitempty"`
	CreatedAt     time.Time           `json:"createdAt"`
	Attachments   []AppAttachment     `json:"attachments,omitempty"`
}

// AppNotificationCardSummary is the scrubbed, client-safe projection of an
// interactive-card render payload used by the message-list read path. It keeps
// only the display keys a client needs to render a card affordance and drops
// free-form text, request/approval blobs, and per-action input schemas/types
// (title, text, request, approval, actions[].inputSchema, actions[].type) that
// must never be exposed through the message-list envelope.
type AppNotificationCardSummary struct {
	SchemaVersion string `json:"schemaVersion,omitempty"`
	Template      string `json:"template,omitempty"`
	// Presentation is retained only when it is a valid server-controlled
	// envelope. The frontend still validates the closed key/args allowlist.
	Presentation json.RawMessage `json:"presentation,omitempty"`
	TitleKey     string          `json:"titleKey"`
	TextKey      string          `json:"textKey,omitempty"`
	Status       string          `json:"status"`
	Fields       json.RawMessage `json:"fields,omitempty"`
	Actions      json.RawMessage `json:"actions,omitempty"`
}

// AppMessage is the API wire message shape expected by the web app client.
type AppMessageTaskContext struct {
	ChannelID  string `json:"channelId"`
	TaskNumber int64  `json:"taskNumber"`
}

type AppMessage struct {
	ID                         string                            `json:"id"`
	Seq                        int64                             `json:"seq"`
	ChannelID                  string                            `json:"channelId"`
	ChannelType                string                            `json:"channelType,omitempty"`
	ClientMessageID            string                            `json:"clientMessageId,omitempty"`
	AuthorProfile              *AuthorProfile                    `json:"authorProfile,omitempty"`
	Source                     *ContributionSource               `json:"source,omitempty"`
	Content                    string                            `json:"content"`
	ResolvedMentions           []ResolvedMention                 `json:"resolvedMentions,omitempty"`
	Metadata                   map[string]any                    `json:"metadata,omitempty"`
	Reactions                  []MessageReactionAggregate        `json:"reactions,omitempty"`
	Attachments                []AppAttachment                   `json:"attachments,omitempty"`
	CreatedAt                  time.Time                         `json:"createdAt"`
	EditedAt                   *time.Time                        `json:"editedAt,omitempty"`
	EditedByMemberID           string                            `json:"editedByMemberId,omitempty"`
	EditRevision               int64                             `json:"editRevision,omitempty"`
	MessageType                string                            `json:"messageType,omitempty"`
	DeliverySummaryPreview     *AppMessageDeliverySummaryPreview `json:"deliverySummaryPreview,omitempty"`
	DeliveryDiagnosticsEnabled *bool                             `json:"deliveryDiagnosticsEnabled,omitempty"`
	ParentChannelID            string                            `json:"parentChannelId,omitempty"`
	ParentChannelType          string                            `json:"parentChannelType,omitempty"`
	ParentMessageID            string                            `json:"parentMessageId,omitempty"`
	TaskContext                *AppMessageTaskContext            `json:"taskContext,omitempty"`
	PinState                   *MessagePinState                  `json:"pinState,omitempty"`
	AppNotificationCard        *AppNotificationCardSummary       `json:"appNotificationCard,omitempty"`
}

// WorkspaceChannel lists a channel and whether the agent has joined it.
type WorkspaceChannel struct {
	Name        string `json:"name"`
	DisplayName string `json:"displayName,omitempty"`
	Description string `json:"description,omitempty"`
	Joined      bool   `json:"joined"`
}

// WorkspaceActor lists a member identity in `/workspace`.
type WorkspaceActor struct {
	Name           string `json:"name"`
	DisplayName    string `json:"displayName,omitempty"`
	Status         string `json:"status,omitempty"`
	Activity       string `json:"activity,omitempty"`
	ActivityDetail string `json:"activityDetail,omitempty"`
	MachineName    string `json:"machineName,omitempty"`
	MachineHost    string `json:"machineHost,omitempty"`
	MachineID      string `json:"machineId,omitempty"`
	OwnerName      string `json:"ownerName,omitempty"`
}

// AgentWorkspaceSnapshotResponse is the list_workspace response with an optional error envelope.
type AgentWorkspaceSnapshotResponse struct {
	Error      string                   `json:"error,omitempty"`
	Channels   []WorkspaceChannel       `json:"channels"`
	Agents     []WorkspaceActor         `json:"agents"`
	Humans     []WorkspaceActor         `json:"humans"`
	Limits     *WorkspaceSnapshotLimits `json:"limits,omitempty"`
	Kind       string                   `json:"kind,omitempty"`
	Limit      int                      `json:"limit,omitempty"`
	HasMore    bool                     `json:"hasMore,omitempty"`
	NextCursor string                   `json:"nextCursor,omitempty"`
}

// WorkspaceSnapshotLimits reports safety caps applied by the server.
type WorkspaceSnapshotLimits struct {
	Channels WorkspaceSnapshotCollectionLimit `json:"channels"`
	Agents   WorkspaceSnapshotCollectionLimit `json:"agents"`
	Humans   WorkspaceSnapshotCollectionLimit `json:"humans"`
}

// WorkspaceSnapshotCollectionLimit reports whether a list was truncated.
type WorkspaceSnapshotCollectionLimit struct {
	Limit     int  `json:"limit"`
	Truncated bool `json:"truncated"`
}

// AgentHistoryResponse is the daemon-compatible history page response.
type AgentHistoryResponse struct {
	Error                    string           `json:"error"`
	TargetKey                string           `json:"targetKey,omitempty"`
	CoversThroughSeq         int64            `json:"coversThroughSeq,omitempty"`
	Messages                 []HistoryMessage `json:"messages"`
	HasMore                  bool             `json:"has_more"`
	NextCursor               int64            `json:"next_cursor,omitempty"`
	CandidateBudgetExhausted bool             `json:"candidate_budget_exhausted,omitempty"`
	HistoryLimited           bool             `json:"historyLimited"`
	HistoryLimitMessage      string           `json:"historyLimitMessage"`
	LastReadSeq              int64            `json:"last_read_seq"`
}

// AgentSearchMessagesResponse returns message search results.
type AgentSearchMessagesResponse struct {
	Error                    string           `json:"error"`
	Messages                 []HistoryMessage `json:"messages"`
	NextCursor               int64            `json:"next_cursor,omitempty"`
	HasMore                  bool             `json:"has_more,omitempty"`
	CandidateBudgetExhausted bool             `json:"candidate_budget_exhausted,omitempty"`
}

// AgentReadCheckResponse returns whether the current agent may read one message.
type AgentReadCheckResponse struct {
	Error   string          `json:"error,omitempty"`
	Allowed bool            `json:"allowed"`
	Reason  string          `json:"reason,omitempty"`
	Message *HistoryMessage `json:"message,omitempty"`
}

// AgentScopeMemberDisplayRow is the private-safe member display row for one scope.
type AgentScopeMemberDisplayRow struct {
	MemberID      string `json:"memberId"`
	MemberType    string `json:"memberType"`
	PublicID      string `json:"publicId,omitempty"`
	DisplayName   string `json:"displayName"`
	Visibility    string `json:"visibility"`
	OwnerMemberID string `json:"ownerMemberId,omitempty"`
}

// AgentScopeMembersResponse returns private-safe scope member display rows.
type AgentScopeMembersResponse struct {
	Error      string                       `json:"error,omitempty"`
	Members    []AgentScopeMemberDisplayRow `json:"members"`
	Limit      int                          `json:"limit,omitempty"`
	HasMore    bool                         `json:"has_more,omitempty"`
	NextCursor string                       `json:"next_cursor,omitempty"`
}
