import type Redis from "ioredis";
import { type ForwardedMessageSnapshot, type ForwardMessageRequest, type Message, type ThreadSummary } from "@slackwsh/contracts";
import { type EntityIdInput } from "./channels";
export interface SendMessageInput {
    clientMsgId: string;
    text: string;
    blocks?: unknown;
    parentId?: EntityIdInput | null;
    isBroadcast?: boolean;
    /** Server-trusted snapshot. ClientSendMessage strips this field, so only
     * forwardMessage can create embedded forwarded-message cards. */
    forwardedMessage?: ForwardedMessageSnapshot;
}
/**
 * The write path from ARCHITECTURE §4.3: allocate the per-channel seq
 * (ADR-001) and insert inside one transaction, then a best-effort broadcast
 * after commit. Idempotent by construction (I3) via `UNIQUE(channel_id,
 * client_msg_id)` — a retry that hits the constraint returns the row that
 * already won, rather than erroring the client's retry loop.
 */
export declare function sendMessage(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, input: SendMessageInput): Promise<{
    type: string;
    workspaceId: number;
    channelId: number;
    id: number;
    createdAt: Date;
    deletedAt: Date | null;
    seq: number;
    clientMsgId: string;
    authorId: number;
    text: string;
    blocks: unknown;
    revision: number;
    parentId: number | null;
    isBroadcast: boolean;
    threadReplyCount: number;
    threadLastReplyAt: Date | null;
    editedAt: Date | null;
}>;
/** Slack-style forwarding: validate access to the source once, snapshot the
 * original author/context, then post a trusted preview into each destination.
 * Destination membership and posting permissions are enforced independently
 * by sendMessage. */
export declare function forwardMessage(redis: Redis, workspaceId: EntityIdInput, sourceChannelId: EntityIdInput, actorUserId: EntityIdInput, sourceMessageId: EntityIdInput, input: ForwardMessageRequest): Promise<{
    type: string;
    workspaceId: number;
    channelId: number;
    id: number;
    createdAt: Date;
    deletedAt: Date | null;
    seq: number;
    clientMsgId: string;
    authorId: number;
    text: string;
    blocks: unknown;
    revision: number;
    parentId: number | null;
    isBroadcast: boolean;
    threadReplyCount: number;
    threadLastReplyAt: Date | null;
    editedAt: Date | null;
}[]>;
export declare function editMessage(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, messageId: EntityIdInput, input: {
    text: string;
    blocks?: unknown;
}): Promise<{
    id: number;
    workspaceId: number;
    channelId: number;
    seq: number;
    clientMsgId: string;
    authorId: number;
    type: string;
    text: string;
    blocks: unknown;
    revision: number;
    parentId: number | null;
    isBroadcast: boolean;
    threadReplyCount: number;
    threadLastReplyAt: Date | null;
    editedAt: Date | null;
    deletedAt: Date | null;
    createdAt: Date;
}>;
export declare function deleteMessage(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, messageId: EntityIdInput): Promise<void>;
export declare function setReaction(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, messageId: EntityIdInput, emoji: string, op: "add" | "remove"): Promise<void>;
export declare function setPin(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, messageId: EntityIdInput, op: "add" | "remove"): Promise<void>;
export declare function markChannelRead(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, seq: number): Promise<void>;
export declare function getThreadSubscriptionStatus(workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, rootMessageId: EntityIdInput): Promise<{
    workspaceId: number;
    channelId: number;
    following: boolean;
    reason: string | null;
    lastReadReplySeq: number;
    unreadReplyCount: number;
    rootMessageId: number;
}>;
export declare function setThreadFollowing(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, rootMessageId: EntityIdInput, following: boolean): Promise<{
    workspaceId: number;
    channelId: number;
    following: boolean;
    reason: string | null;
    lastReadReplySeq: number;
    unreadReplyCount: number;
    rootMessageId: number;
}>;
export declare function markThreadRead(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, rootMessageId: EntityIdInput, seq: number): Promise<{
    workspaceId: number;
    channelId: number;
    following: boolean;
    reason: string | null;
    lastReadReplySeq: number;
    unreadReplyCount: number;
    rootMessageId: number;
}>;
export declare function listFollowedThreads(workspaceId: EntityIdInput, actorUserId: EntityIdInput, limit?: number): Promise<ThreadSummary[]>;
export interface ScrollbackOptions {
    afterSeq?: number;
    beforeSeq?: number;
    limit: number;
}
/** Channel scrollback (§5.3 catch-up mechanism): top-level messages only,
 * i.e. `parent_id IS NULL OR is_broadcast` — thread replies live in the
 * thread view (getThread), per I5's channel/thread split (ADR-014). */
/** Resolve one permalink target without forcing the client to page through
 * all older history. Access and deletion rules match the ordinary read path. */
export declare function getMessage(workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, messageId: EntityIdInput): Promise<Message>;
export declare function getScrollback(workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, opts: ScrollbackOptions): Promise<{
    type: "text" | "system";
    id: number;
    createdAt: string;
    workspaceId: number;
    channelId: number;
    parentId: number | null;
    authorId: number;
    text: string;
    seq: number;
    clientMsgId: string;
    blocks: {
        v: 1;
        doc: Record<string, unknown>;
        forwardedMessage?: {
            createdAt: string;
            messageId: number;
            channelId: number;
            parentId: number | null;
            channelName: string | null;
            channelType: "public" | "private" | "dm" | "group_dm";
            authorId: number;
            authorName: string;
            authorAvatarUrl: string | null;
            text: string;
            attachmentNames: string[];
        } | undefined;
    };
    revision: number;
    isBroadcast: boolean;
    threadReplyCount: number;
    threadLastReplyAt: string | null;
    editedAt: string | null;
    deletedAt: string | null;
    reactions?: {
        emoji: string;
        count: number;
        reactedByMe: boolean;
    }[] | undefined;
}[]>;
export declare function getThread(workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, rootMessageId: EntityIdInput): Promise<{
    type: "text" | "system";
    id: number;
    createdAt: string;
    workspaceId: number;
    channelId: number;
    parentId: number | null;
    authorId: number;
    text: string;
    seq: number;
    clientMsgId: string;
    blocks: {
        v: 1;
        doc: Record<string, unknown>;
        forwardedMessage?: {
            createdAt: string;
            messageId: number;
            channelId: number;
            parentId: number | null;
            channelName: string | null;
            channelType: "public" | "private" | "dm" | "group_dm";
            authorId: number;
            authorName: string;
            authorAvatarUrl: string | null;
            text: string;
            attachmentNames: string[];
        } | undefined;
    };
    revision: number;
    isBroadcast: boolean;
    threadReplyCount: number;
    threadLastReplyAt: string | null;
    editedAt: string | null;
    deletedAt: string | null;
    reactions?: {
        emoji: string;
        count: number;
        reactedByMe: boolean;
    }[] | undefined;
}[]>;
/** Explicit user action allowed to move I4's read cursor backwards. */
export declare function markMessageUnread(redis: Redis, workspaceId: EntityIdInput, channelId: EntityIdInput, actorUserId: EntityIdInput, messageId: EntityIdInput): Promise<{
    lastReadSeq: number;
    unreadCount: number;
}>;
//# sourceMappingURL=messages.d.ts.map