/**
 * Refreshable Stream
 *
 * Helper estándar para vistas que consumen datos de Firestore. Soporta DOS
 * modos — el caller decide cuál vía la `factory`:
 *
 *  - **one-shot** (recomendado por defecto): `() => from(svc.getAllOnce())`.
 *    Carga una vez y completa. Más barato — sin listener vivo.
 *  - **real-time**: `() => svc.getAll()`. Listener Firestore que auto-actualiza.
 *    Solo donde importa (inbox de notificaciones, badges).
 *
 * En ambos modos la primera suscripción se gatea por `firebaseAuthReady`
 * (sesión de Firebase Auth lista) — así el listener/lectura nunca se adjunta
 * antes de que `request.auth` esté disponible en las reglas de Firestore, lo
 * que cierra la ventana de `permission-denied` en cold start de PWA.
 *
 * El `retry` con backoff corto es solo red de seguridad para reconexiones
 * transitorias (no para cubrir cold start — eso lo cubre el gate de auth).
 */
import { Injector, Signal } from '@angular/core';
import { Observable } from 'rxjs';
/** Opciones de configuración para `createRefreshableStream`. */
export interface RefreshableStreamOptions<T> {
    /**
     * Valor emitido cuando la factory falla tras agotar los reintentos.
     * Default: `null`.
     */
    fallback?: T;
    /**
     * Número máximo de reintentos ante un error de la factory.
     * Backoff corto — NO cubre cold start (eso lo hace el gate de auth), solo
     * reconexiones transitorias. Default: 4.
     */
    retryCount?: number;
    /**
     * Delay base del backoff (ms). El delay efectivo crece exponencialmente
     * acotado: 500ms → 1s → 2s ... Default: 500.
     */
    retryBaseDelayMs?: number;
    /**
     * Si `false`, NO espera a `firebaseAuthReady` antes de la primera
     * suscripción. Útil para streams que no leen Firestore. Default: `true`.
     */
    gateOnFirebaseAuth?: boolean;
    /**
     * Timeout (ms) del gate de Firebase Auth. Si la sesión de Firebase Auth no
     * se establece en este tiempo, el stream procede igual (la factory correrá
     * y, si no hay permiso, terminará en estado `error` — NUNCA en skeleton
     * infinito). Muy por encima de cualquier handshake real. Default: 20000.
     */
    authGateTimeoutMs?: number;
    /**
     * Timeout (ms) de la PRIMERA emisión de la factory. Si la factory no emite
     * ni un valor ni un error en este tiempo (caso típico: un servicio Firestore
     * que nunca se inicializó → `EMPTY` → silencio total), el stream pasa a
     * estado `error` en vez de quedarse en skeleton perpetuo. Default: 20000.
     */
    firstEmitTimeoutMs?: number;
    /**
     * Injector explícito. Solo necesario si `createRefreshableStream` se llama
     * fuera de un injection context (raro). Por defecto usa `inject(Injector)`.
     */
    injector?: Injector;
}
/**
 * Resultado de `createRefreshableStream`.
 */
export interface RefreshableStream<T> {
    /** Datos actuales. `null` mientras la primera emisión no ha llegado. */
    readonly data: Signal<T | null>;
    /** `true` mientras se espera la primera emisión de la suscripción actual. */
    readonly loading: Signal<boolean>;
    /** `true` si la factory falló tras agotar los reintentos. */
    readonly error: Signal<boolean>;
    /**
     * Re-suscribe la factory desde cero (nuevo listener / nueva lectura).
     * Es lo que registra el `PageRefreshService` como handler de pull-to-refresh,
     * y también el "reconectar manual" si un listener murió.
     */
    reload: () => void;
}
/**
 * Crea un stream refrescable a partir de una factory de Observable.
 *
 * DEBE llamarse en un injection context (field initializer o constructor) —
 * usa `toSignal`/`toObservable`/`inject` internamente.
 *
 * @param factory - Función que produce el Observable a consumir. El caller
 *   decide el modo: `() => from(svc.getAllOnce())` (one-shot) o
 *   `() => svc.getAll()` (real-time).
 * @param options - Configuración opcional (fallback, retry, gate).
 *
 * @example
 * ```typescript
 * // one-shot (recomendado por defecto)
 * private readonly stream = createRefreshableStream(
 *   () => from(this.svc.getAllOnce()),
 * );
 *
 * // real-time (inbox)
 * private readonly stream = createRefreshableStream(
 *   () => this.notifs.getAll(50),
 * );
 *
 * readonly items = this.stream.data;
 * readonly loading = this.stream.loading;
 *
 * ionViewWillEnter() {
 *   this.pageRefresh.register(() => this.stream.reload());
 * }
 * ```
 */
export declare function createRefreshableStream<T>(factory: () => Observable<T>, options?: RefreshableStreamOptions<T>): RefreshableStream<T>;
