import { OnDestroy, OnInit } from '@angular/core';
import { EmptyStateMetadata } from '../../molecules/empty-state/types';
import { ButtonMetadata } from '../../types';
import { NotificationDocument } from '../../../services/firebase/notifications.service';
import { NotificationsViewConfig } from './types';
import * as i0 from "@angular/core";
type GroupKey = 'today' | 'thisMonth' | 'earlier';
interface NotificationGroup {
    key: GroupKey;
    label: string;
    items: NotificationDocument[];
}
type ResolvedIcon = {
    kind: 'ionicon';
    name: string;
    color?: string;
} | {
    kind: 'image';
    src: string;
} | {
    kind: 'avatar';
    src: string;
};
/**
 * `val-notifications-view` — inbox de notificaciones full-feature autocontenido
 * (organism). Promovido desde `showcase` bajo el proceso de ADR-021.
 *
 * Separado de `/app/settings/notifications` (que controla permiso FCM + master
 * toggle). Aquí el user lee/abre/marca-leídas sus mensajes.
 *
 * - **Stream real-time** vía `NotificationsService.getAll(maxLoad)` envuelto en
 *   `createRefreshableStream` (gateado por `firebaseAuthReady`, retry corto,
 *   `firstEmitTimeoutMs: 15000`). Estados: loading (skeleton), error
 *   (`val-empty-state` + reintentar), empty (`val-empty-state` + CTA), data
 *   (lista agrupada Hoy / Este mes / Anteriores).
 * - **Abrir** una notif → `NotificationActionService.open()` (markRead +
 *   switch-org + navegar/handoff cross-app). Hook `onNotificationOpen` opcional.
 * - **Marcar todas como leídas** (gateado por `enableMarkAll`).
 * - **CTA push-off** cuando el permiso del navegador no está concedido (gateado
 *   por `showPushOffCta`); navega a `settingsNotificationsPath`.
 * - **Paginación soft** — slice local (`pageSize`, +`pageSize` por click) sobre el
 *   cache del stream; el tope de fetch es `maxLoad`.
 * - **i18n auto-registrado** es/en bajo `i18nNamespace` (default `Notifications`).
 *
 * NO renderiza ion-content — vive dentro de val-page-wrapper. `Router` y
 * `ActivatedRoute` se inyectan `{ optional: true }` → funciona sin router
 * (embebida / Storybook). El forward-compat icon resolver lee `notif.payload.icon`
 * si existe (`{ type, value, color? }`), cae a un mapa por `notif.type`, luego a
 * `notifications-outline`.
 */
export declare class NotificationsViewComponent implements OnInit, OnDestroy {
    private nav;
    private i18n;
    private notifs;
    private action;
    private toast;
    private errors;
    private auth;
    private pageRefresh;
    private route;
    /**
     * Config vía @Input (object-first). Si no se pasa, se cae al route data
     * `notificationsConfig` (poblado por `provideValtechNotificationsRoutes`).
     * `resolvedConfig` mergea con los defaults — `@Input` gana sobre route data.
     */
    config?: NotificationsViewConfig;
    readonly resolvedConfig: import("@angular/core").Signal<Required<Omit<NotificationsViewConfig, "onNotificationOpen">> & Pick<NotificationsViewConfig, "onNotificationOpen">>;
    /** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
    private get ns();
    /** Paso de paginación soft (revela +N por "cargar más"). */
    private get pageStep();
    private readonly _expanded;
    private readonly _pageSize;
    private readonly _bulkBusy;
    private readonly _loadingMore;
    /**
     * Push activado = permiso del navegador en `granted`. Si NO está activado,
     * el user puede leer el inbox (Firestore) pero NO recibirá push en su
     * dispositivo → mostramos una card que lo invita a ir a configuración.
     * Se evalúa en cada montaje de la vista.
     */
    readonly pushEnabled: import("@angular/core").WritableSignal<boolean>;
    /**
     * Stream firestore real-time vía el helper estándar `createRefreshableStream`
     * (modo real-time: factory devuelve un listener vivo `notifs.getAll(maxLoad)`).
     *
     * El helper gatea la primera suscripción por `firebaseAuthReady`, aplica un
     * `retry` corto con backoff y, tras agotar reintentos, emite el fallback (`[]`)
     * y marca `error` — estado de error en UI, no skeleton infinito. `reload()`
     * re-suscribe el stream completo (lo usa el pull-to-refresh).
     */
    private readonly _stream;
    /** True si el stream falló tras agotar reintentos → muestra estado de error. */
    readonly streamError: import("@angular/core").Signal<boolean>;
    readonly loading: import("@angular/core").Signal<boolean>;
    /**
     * Notifs reales mostradas. Filtramos docs sin título Y sin body — son ruido
     * (típicamente sentinel/system writes pre-schema con title/body opcionales).
     */
    readonly allNotifs: import("@angular/core").Signal<NotificationDocument[]>;
    readonly hasMore: import("@angular/core").Signal<boolean>;
    readonly showMarkAll: import("@angular/core").Signal<boolean>;
    /** Sub-conjunto paginado, agrupado por período. */
    readonly groups: import("@angular/core").Signal<NotificationGroup[]>;
    readonly pageTitle: import("@angular/core").Signal<string>;
    readonly pageDescription: import("@angular/core").Signal<string>;
    readonly ctaTitle: import("@angular/core").Signal<string>;
    readonly ctaHint: import("@angular/core").Signal<string>;
    readonly ctaButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
    /**
     * Estado de error de carga: convierte el error del stream en
     * `EmptyStateMetadata` via el helper canónico `createErrorStateProps`.
     * El helper decide variante (`offline` vs `error`) por `isNetwork`.
     * Null cuando el stream no ha fallado.
     */
    readonly errorState: import("@angular/core").Signal<EmptyStateMetadata>;
    /**
     * Estado vacío (lista real = 0 notificaciones, sin error de carga).
     * Se construye manualmente con `variant: 'empty'` — sin helper de error.
     */
    readonly emptyStateProps: import("@angular/core").Signal<EmptyStateMetadata>;
    readonly seeMore: import("@angular/core").Signal<string>;
    readonly seeLess: import("@angular/core").Signal<string>;
    readonly markAllButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
    readonly loadMoreButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
    constructor();
    /**
     * Registra el pull-to-refresh estándar. Usamos `ngOnInit`/`ngOnDestroy`
     * (NO `ionViewWillEnter`) porque `val-page-wrapper` usa `<router-outlet>`
     * plano — los hooks `ionView*` solo disparan dentro de `<ion-router-outlet>`.
     */
    ngOnInit(): void;
    /** Quita el handler al destruir la vista — el refresher desaparece. */
    ngOnDestroy(): void;
    /**
     * Refresh manual: re-suscribe el stream Firestore (listener nuevo) vía el
     * helper. Resuelve tras un margen breve — el stream es real-time y re-emite
     * en milisegundos; el delay sólo mantiene el spinner visible lo justo.
     */
    private reload;
    openButtonProps(): Partial<ButtonMetadata>;
    isExpanded(id: string): boolean;
    toggleExpand(id: string): void;
    isLong(body: string | undefined): boolean;
    /**
     * Icon resolver con orden de fallback:
     * 1. notif.payload.icon (forward-compat, sin breaking change en schema)
     * 2. mapa por notif.type
     * 3. default notifications-outline
     */
    resolveIcon(n: NotificationDocument): ResolvedIcon;
    ioniconName(n: NotificationDocument): string;
    ioniconColor(n: NotificationDocument): string | undefined;
    imageSrc(n: NotificationDocument): string;
    ionColor(token: string | undefined): string;
    relativeTime(n: NotificationDocument): string;
    /** Devuelve label "Desde {appName}" si la notif viene de otra app, sino null. */
    showCrossAppBadge(n: NotificationDocument): string | null;
    onOpen(n: NotificationDocument): Promise<void>;
    onMarkAll(): Promise<void>;
    onLoadMore(): void;
    onGoToSettings(): void;
    private bucketOf;
    private tt;
    static ɵfac: i0.ɵɵFactoryDeclaration<NotificationsViewComponent, never>;
    static ɵcmp: i0.ɵɵComponentDeclaration<NotificationsViewComponent, "val-notifications-view", never, { "config": { "alias": "config"; "required": false; }; }, {}, never, never, true, never>;
}
export {};
