import type { BrokerMsgIdHeader } from "./contract.js";

/**
 * Effectively Once: Try to dedupe at the publisher side (publisher = the one who sends the message) by using
 * a deterministic message id.
 */
type BrokerEffectivelyOncePublisher = {
    msgIdHeader?: BrokerMsgIdHeader;
};

/**
 * Effectively Once: Try to dedupe at the replay stream side (replay stream = the one who stores the message)
 * by using a deduplication window beside the message id.
 */
type BrokerEffectivelyOnceReplayStream = {
    /**
     * Deduplication window in milliseconds.
     * - Must match the retry horizon (>= maximum retry duration).
     * - The stream must retain data at least as long (maxAge >= window).
     */
    dedupeWindowMs?: number;
};

/**
 * Effectively Once: Try to dedupe at the subscriber side (subscriber = the one who receives the message)
 * by using a time to live for the seen key.
 *
 * Example: When receiving the message, write the message id to a unique list in Redis and if the message
 * id is already within the list, do not process the message again. This could be greatly be combined with
 * a `acquireLock()` functionality to ensure that only one instance of the subscriber processes the message.
 */
type BrokerEffectivelyOnceSubscriber = {
    /**
     * Time to live for the seen key in milliseconds.
     *
     * Must be >= time window of all retries/redeliveries.
     */
    ttlMsSeenKey?: number;
};

type BrokerEffectivelyOnceNone = {
    effectivelyOnce: "none";
};

type BrokerEffectivelyOnceNoGuarantee = {
    effectivelyOnce: "publisher+subscriber";
} & BrokerEffectivelyOncePublisher &
    BrokerEffectivelyOnceSubscriber;

type BrokerEffectivelyOnceGuarantee = {
    effectivelyOnce: "publisher+broker+subscriber";
} & BrokerEffectivelyOncePublisher &
    BrokerEffectivelyOnceSubscriber &
    BrokerEffectivelyOnceReplayStream;

export {
    type BrokerEffectivelyOncePublisher,
    type BrokerEffectivelyOnceReplayStream,
    type BrokerEffectivelyOnceSubscriber,
    type BrokerEffectivelyOnceNone,
    type BrokerEffectivelyOnceNoGuarantee,
    type BrokerEffectivelyOnceGuarantee,
};
