import type { BrokerAckPolicy, BrokerDeliverPolicy, BrokerRetention } from "./contract.js";
import type {
    BrokerEffectivelyOnceGuarantee,
    BrokerEffectivelyOnceNoGuarantee,
    BrokerEffectivelyOnceNone,
} from "./effectively-once.js";

/**
 * Broadcast without any guarantees that the message will be delivered to all subscribers
 * (i.e., all replicas of the same service).
 *
 * - Volatile, `at-most-once` semantic (no redeliveries, but message loss possible).
 * - No broker deduplication.
 * - Effectively Once optional (Publisher + Subscriber) through message ID
 *
 * Example use cases:
 * - Real-time metrics and telemetry data where occasional loss is acceptable
 * - System health pings and heartbeat signals
 * - Progress bar updates
 *
 * Example: Use NATS Core instead of JetStream (`at-most-once`).
 */
type BrokerBroadcastNoGuarantee = {
    type: "broadcast+no-guarantee";
    /**
     * To make sure the message is delivered to all subscribers, messages are published to a queue first
     * and then consumed from the queue by all subscribers.
     *
     * Use `{purpose}` as placeholder for the purpose of the durable subscription.
     * Use `{durable}` as placeholder for the durable name (the replica ID or slot index).
     *
     * @default Automatically generated with `{durable}` and `{purpose}` placeholder
     * @example
     * ```typescript
     * queue: "q_orders_{durable}_{purpose}_v1" // {durable} and {purpose} will be replaced at subscription time
     * ```
     */
    queue?: string;
} & (BrokerEffectivelyOnceNone | BrokerEffectivelyOnceNoGuarantee);

/**
 * Broadcast with a guarantee that the message will be delivered at least once to all subscribers.
 *
 * - Persistence/Replay possible, `at-least-once` semantic.
 * - Dedupe + double confirmation + Subscriber-Idempotency are enforced via "effectively once".
 *
 * Example use cases:
 * - System-wide announcements (maintenance notifications sent to all connected clients)
 * - Cache invalidation events (all application instances clear the same cached data)
 *
 * Example: Use JetStream instead of NATS Core (`at-least-once`).
 */
type BrokerBroadcastGuarantee = {
    type: "broadcast+guarantee";
    /**
     * Name of the stream to publish the message to (bridge between publisher and subscriber to be able
     * to replay the message and hold it for a while).
     *
     * @default Automatically generated
     */
    stream?: string;
    /**
     * Name of the durable subscription to use for the stream.
     *
     * Use `{purpose}` as placeholder for the purpose of the durable subscription.
     * Use `{durable}` as placeholder for the durable name (the replica ID or slot index).
     *
     * @default Automatically generated
     */
    durable?: string;
    /**
     * Controls how the consumer identifier is derived when running multiple replicas.
     *
     * If `true` (default), the identifier is based on a **stable replica slot/index** (e.g. `service.3`).
     * This keeps the consumer identity **stable per replica position** across restarts or rescheduling,
     * allowing the replica in that slot to continue using the same consumer state.
     *
     * If `false`, the identifier is based on a **unique instance ID** (e.g. `service.ab12cd...`).
     * This makes the consumer identity **unique per process instance**, so a restart typically results
     * in a new identifier and therefore a fresh consumer state. This is useful when you want strict
     * isolation per instance, but it can require cleanup of old identifiers depending on your system.
     *
     * ### Example (Docker Swarm + JetStream, stickyDurable = true)
     * Durable name uses the task slot:
     * - Service: `payments`
     * - Task Slot: `2`
     * - Durable: `payments.2`
     *
     * Behavior:
     * - The replica in slot `2` restarts/reschedules → it reuses `payments.2` and continues from prior state.
     *
     * ### Example (Docker Swarm + JetStream, stickyDurable = false)
     * Durable name uses the task ID:
     * - Service: `payments`
     * - Task ID: `4k2p9xq7m3...`
     * - Durable: `payments.4k2p9xq7m3`
     *
     * Behavior:
     * - Restart → new task ID → new durable → new consumer identity; old durables may remain until cleaned up.
     *
     * @default true
     */
    stickyDurable?: boolean;
    /**
     * Max age of the message in the stream in milliseconds. Afterward, it is removed from the stream.
     *
     * @default 60 * 60 * 1000 // 1 hour
     */
    ttlMsOnStream?: number;
} & (BrokerRetention & {
    // `workqueue` is not supported for broadcast
    retention?: "limits" | "interest";
}) &
    BrokerDeliverPolicy &
    BrokerAckPolicy &
    BrokerEffectivelyOnceGuarantee;

export { type BrokerBroadcastNoGuarantee, type BrokerBroadcastGuarantee };
