import { OnDestroy } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthStateService } from './auth-state.service';
import { TokenService } from './token.service';
import { AuthStorageService } from './storage.service';
import { AuthSyncService } from './sync.service';
import { SigninRequest, SigninResponse, SignupRequest, SignupResponse, VerifyEmailRequest, VerifyEmailResponse, ResendCodeRequest, ResendCodeResponse, MFAVerifyResponse, RefreshResponse, GetPermissionsResponse, GetProfileResponse, UpdateProfileRequest, UpdateProfileResponse, MFASetupResponse, MFAConfirmResponse, MFADisableRequest, MFADisableResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, ActivateAccountRequest, ActivateAccountResponse, ChangePasswordResponse, DeleteAccountResponse, SendDeleteAccountCodeResponse, SwitchOrgResponse, MFAMethod, AuthError, ValtechAuthConfig, EnableNotificationsResult, NotificationPermissionState, RegisterDeviceResult, TOTPSetupResponse, TOTPVerifySetupResponse, TOTPDisableResponse, RegenerateBackupCodesResponse, BackupCodesCountResponse, OAuthProvider, LinkedProvider, HasPasswordResponse, UpdateHandleResponse, CheckHandleResponse, UpdateAvatarRequest, UpdateAvatarResponse, InitiateEmailChangeResponse, ConfirmEmailChangeStep1Response, ConfirmEmailChangeStep2Response } from './types';
import { OAuthService } from './oauth.service';
import { FirebaseService, MessagingService } from '../firebase';
import { I18nService } from '../i18n';
import { Firestore } from '@angular/fire/firestore';
import { ConfirmationDialogService } from '../confirmation-dialog/confirmation-dialog.service';
import * as i0 from "@angular/core";
/**
 * Servicio principal de autenticación.
 *
 * @example
 * ```typescript
 * import { AuthService } from 'valtech-components';
 *
 * @Component({...})
 * export class LoginComponent {
 *   private auth = inject(AuthService);
 *
 *   async login() {
 *     await firstValueFrom(this.auth.signin({ email, password }));
 *     if (this.auth.mfaPending().required) {
 *       // Mostrar UI de MFA
 *     } else {
 *       this.router.navigate(['/']);
 *     }
 *   }
 * }
 * ```
 */
export declare class AuthService implements OnDestroy {
    private config;
    private http;
    private router;
    private stateService;
    private tokenService;
    private storageService;
    private syncService;
    private firebaseService;
    private oauthService;
    private messagingService;
    private i18nService;
    private confirmationService;
    private firestoreInstance;
    private refreshTimerId;
    private syncSubscription;
    private firestoreRBACUnsubscribe;
    constructor(config: ValtechAuthConfig | null, http: HttpClient, router: Router, stateService: AuthStateService, tokenService: TokenService, storageService: AuthStorageService, syncService: AuthSyncService, firebaseService: FirebaseService, oauthService: OAuthService, messagingService: MessagingService | null, i18nService: I18nService | null, confirmationService: ConfirmationDialogService, firestoreInstance: Firestore | null);
    /** Estado completo de autenticación */
    readonly state: import("@angular/core").Signal<import("./types").AuthState>;
    /** Usuario está autenticado */
    readonly isAuthenticated: import("@angular/core").Signal<boolean>;
    /** Estado de carga */
    readonly isLoading: import("@angular/core").Signal<boolean>;
    /** Información del usuario */
    readonly user: import("@angular/core").Signal<import("./types").AuthUser>;
    /** Token de acceso */
    readonly accessToken: import("@angular/core").Signal<string>;
    /** Roles del usuario */
    readonly roles: import("@angular/core").Signal<string[]>;
    /** Permisos del usuario */
    readonly permissions: import("@angular/core").Signal<string[]>;
    /** Usuario es super admin */
    readonly isSuperAdmin: import("@angular/core").Signal<boolean>;
    /** Estado de MFA pendiente */
    readonly mfaPending: import("@angular/core").Signal<import("./types").MFAPendingState>;
    /** Error actual */
    readonly error: import("@angular/core").Signal<AuthError>;
    /**
     * Inicializa el servicio de autenticación.
     * Llamado automáticamente por provideValtechAuth.
     */
    initialize(): Promise<void>;
    ngOnDestroy(): void;
    /**
     * Inicia sesión con email y contraseña.
     * Detecta automáticamente la plataforma para identificar dispositivos nuevos.
     */
    signin(request: SigninRequest): Observable<SigninResponse>;
    /**
     * Inicia sesión con OAuth (Google, Apple, Microsoft).
     * Abre un popup para el flujo de autenticación.
     *
     * @param provider - Proveedor OAuth ('google', 'apple', 'microsoft')
     * @returns Observable que emite SigninResponse cuando se completa
     *
     * @example
     * ```typescript
     * this.auth.signinWithOAuth('google').subscribe({
     *   next: () => this.router.navigate(['/']),
     *   error: (err) => console.error('OAuth failed:', err)
     * });
     * ```
     */
    signinWithOAuth(provider: OAuthProvider): Observable<SigninResponse>;
    /**
     * Vincula un proveedor OAuth adicional a la cuenta actual.
     * Requiere que el usuario esté autenticado.
     *
     * @param provider - Proveedor OAuth a vincular
     */
    linkOAuthProvider(provider: OAuthProvider): Observable<{
        success: boolean;
    }>;
    /**
     * Obtiene los proveedores OAuth vinculados al usuario.
     */
    getLinkedProviders(): Observable<LinkedProvider[]>;
    /**
     * Desvincula un proveedor OAuth de la cuenta.
     *
     * @param provider - Proveedor a desvincular
     */
    unlinkOAuthProvider(provider: OAuthProvider): Observable<{
        success: boolean;
    }>;
    /**
     * Establece contraseña para usuarios que solo tienen OAuth.
     * Permite que usuarios OAuth-only puedan también usar email/password.
     *
     * @param password - Nueva contraseña
     */
    setPasswordForOAuthUser(password: string): Observable<{
        success: boolean;
    }>;
    /**
     * Verifica si el usuario tiene contraseña establecida.
     * Útil para mostrar/ocultar opciones de cambio de contraseña.
     */
    checkHasPassword(): Observable<HasPasswordResponse>;
    /**
     * Registra un nuevo usuario.
     * El usuario queda en estado PENDING hasta verificar su email.
     */
    signup(request: SignupRequest): Observable<SignupResponse>;
    /**
     * Verifica email con código de 6 dígitos.
     * Si es exitoso, hace auto-login y retorna tokens.
     */
    verifyEmail(request: VerifyEmailRequest): Observable<VerifyEmailResponse>;
    /**
     * Reenvía código de verificación al email.
     */
    resendCode(request: ResendCodeRequest): Observable<ResendCodeResponse>;
    /**
     * Verifica código MFA.
     */
    verifyMFA(code: string): Observable<MFAVerifyResponse>;
    /**
     * Refresca el token de acceso.
     * Implementa token rotation: cada refresh genera un nuevo refresh token
     * que el cliente debe guardar para el próximo refresh.
     */
    refreshAccessToken(): Observable<RefreshResponse>;
    /**
     * Maneja autenticación exitosa desde fuentes externas (OAuth, etc).
     * Guarda tokens, actualiza estado, inicia Firebase si corresponde.
     *
     * @param authResult - Resultado de autenticación con tokens
     *
     * @example
     * ```typescript
     * // Desde un flujo OAuth externo
     * externalOAuth.signIn().subscribe({
     *   next: (result) => {
     *     this.authService.setExternalAuth(result);
     *   }
     * });
     * ```
     */
    setExternalAuth(authResult: {
        accessToken: string;
        refreshToken: string;
        firebaseToken?: string;
        expiresIn: number;
        roles?: string[];
        permissions?: string[];
    }): void;
    /**
     * Cierra sesión tras pedir confirmación al usuario.
     *
     * Muestra un diálogo nativo (estilo destructivo). Si el usuario confirma,
     * ejecuta `logout()`. Si cancela, no pasa nada.
     *
     * Texto por defecto desde `_global` i18n: `logoutConfirmTitle`,
     * `logoutConfirmMessage`, `logout`, `cancel`. Override via `opts`.
     *
     * @returns true si el usuario confirmó (logout ejecutado), false si canceló.
     *
     * @example
     * onLogoutClick() { this.auth.logoutWithConfirmation(); }
     */
    logoutWithConfirmation(opts?: {
        title?: string;
        message?: string;
        confirmText?: string;
        cancelText?: string;
    }): Promise<boolean>;
    /**
     * Cierra sesión.
     */
    logout(): Promise<void>;
    /**
     * Configura MFA para el usuario.
     */
    setupMFA(method: MFAMethod, phone?: string): Observable<MFASetupResponse>;
    /**
     * Confirma la configuración de MFA.
     */
    confirmMFA(code: string): Observable<MFAConfirmResponse>;
    /**
     * Deshabilita MFA. Acepta `password` o `mfaCode` (uno requerido).
     * `mfaCode` es para usuarios OAuth-only con TOTP que no tienen contraseña.
     */
    disableMFA(input: MFADisableRequest): Observable<MFADisableResponse>;
    sendMFADisableCode(): Observable<{
        operationId: string;
    }>;
    /**
     * Inicia configuración de TOTP MFA.
     * Retorna el secreto, URL para QR code y códigos de respaldo.
     */
    setupTOTP(): Observable<TOTPSetupResponse>;
    /**
     * Verifica el código TOTP y activa MFA.
     * Debe llamarse después de setupTOTP con el código del authenticator.
     */
    verifyTOTPSetup(code: string): Observable<TOTPVerifySetupResponse>;
    /**
     * Regenera los códigos de respaldo TOTP.
     * Los códigos anteriores son invalidados.
     */
    regenerateBackupCodes(): Observable<RegenerateBackupCodesResponse>;
    /**
     * Obtiene la cantidad de códigos de respaldo restantes.
     */
    getBackupCodesCount(): Observable<BackupCodesCountResponse>;
    /**
     * Desactiva TOTP MFA (requiere contraseña).
     */
    disableTOTP(password: string): Observable<TOTPDisableResponse>;
    /**
     * Cambia la organización activa del usuario.
     * Genera un nuevo Firebase token con el activeOrg actualizado.
     *
     * @param organizationId - ID de la organización a la que cambiar
     * @returns Observable con el nuevo Firebase token y activeOrg
     *
     * @example
     * ```typescript
     * await firstValueFrom(this.auth.switchOrg('org_xyz789'));
     * // Firebase ya está re-autenticado con la nueva org
     * const activeOrg = await this.firebase.getActiveOrg();
     * ```
     */
    switchOrg(organizationId: string): Observable<SwitchOrgResponse>;
    /**
     * Obtiene el perfil del usuario autenticado.
     * Incluye información de MFA y teléfono. Hidrata el state automáticamente
     * con `name/handle/avatarUrl/phone` para que `auth.user()` los retorne.
     */
    getProfile(): Observable<GetProfileResponse>;
    /**
     * Actualiza el perfil del usuario. Sincroniza state con los nuevos values
     * (name/phone) — el backend response no los echo'a pero el caller ya tiene
     * los valores que mandó.
     */
    updateProfile(request: UpdateProfileRequest): Observable<UpdateProfileResponse>;
    /**
     * Actualiza el avatar del usuario en el backend. Sincroniza state con el
     * `avatarUrl` retornado para que el header / dashboard se refresquen sin
     * necesidad de un getProfile adicional.
     */
    updateAvatar(request: UpdateAvatarRequest): Observable<UpdateAvatarResponse>;
    /**
     * Inicia el proceso de recuperación de contraseña.
     * Envía un código al email del usuario.
     */
    forgotPassword(request: ForgotPasswordRequest): Observable<ForgotPasswordResponse>;
    /**
     * Resetea la contraseña usando el código enviado por email.
     */
    resetPassword(request: ResetPasswordRequest): Observable<ResetPasswordResponse>;
    /**
     * Activa una cuenta pre-aprovisionada por una organización (ADR-023): define
     * la contraseña con el token del enlace de email. En éxito el backend devuelve
     * tokens de auto-signin → el usuario queda logueado (mismo flujo que verify-email).
     */
    activateAccount(request: ActivateAccountRequest): Observable<ActivateAccountResponse>;
    /**
     * Cambia la contraseña del usuario autenticado.
     * Requiere la contraseña actual para verificación.
     */
    changePassword(currentPassword: string, newPassword: string): Observable<ChangePasswordResponse>;
    initiateEmailChange(currentPassword: string, newEmail: string): Observable<InitiateEmailChangeResponse>;
    confirmEmailChangeStep1(code: string): Observable<ConfirmEmailChangeStep1Response>;
    confirmEmailChangeStep2(code: string): Observable<ConfirmEmailChangeStep2Response>;
    /**
     * Elimina la cuenta del usuario (soft delete).
     * Requiere confirmación de contraseña por seguridad.
     * Después de eliminar, cierra sesión automáticamente.
     *
     * @param password - Contraseña actual para confirmar
     * @returns Observable con resultado de la eliminación
     *
     * @example
     * ```typescript
     * async confirmDeleteAccount(password: string) {
     *   try {
     *     const result = await firstValueFrom(this.auth.deleteAccount(password));
     *     console.log(result.message); // "Tu cuenta ha sido eliminada..."
     *     // Usuario es redirigido automáticamente al login
     *   } catch (error) {
     *     // Manejar error (contraseña incorrecta, etc)
     *   }
     * }
     * ```
     */
    /**
     * Envía un código OTP al email del usuario para confirmar la eliminación.
     * Solo aplica a usuarios OAuth sin contraseña (`hasPassword() === false`).
     */
    sendDeleteAccountCode(): Observable<SendDeleteAccountCodeResponse>;
    /**
     * Elimina la cuenta del usuario (soft delete).
     * - Usuarios con contraseña: pasar `{ password }`.
     * - Usuarios OAuth sin contraseña: pasar `{ code }` (obtenido via sendDeleteAccountCode).
     * Después de eliminar, cierra sesión y redirige al login automáticamente.
     */
    deleteAccount(credentials: {
        password?: string;
        code?: string;
    }): Observable<DeleteAccountResponse>;
    /**
     * Obtiene los permisos actualizados del backend.
     */
    fetchPermissions(): Observable<GetPermissionsResponse>;
    /**
     * Verifica si el usuario tiene un permiso específico.
     * Formato: "resource:action" (ej: "templates:edit")
     */
    hasPermission(permission: string): boolean;
    /**
     * Verifica si el usuario tiene alguno de los permisos dados.
     */
    hasAnyPermission(permissions: string[]): boolean;
    /**
     * Verifica si el usuario tiene todos los permisos dados.
     */
    hasAllPermissions(permissions: string[]): boolean;
    /**
     * Verifica si el usuario tiene un rol específico.
     */
    hasRole(role: string): boolean;
    /**
     * Actualiza el handle (@username) del usuario.
     * @param handle - Nuevo handle (sin @, ej: "victorv")
     */
    updateHandle(handle: string): Observable<UpdateHandleResponse>;
    /**
     * Verifica si un handle está disponible.
     * @param handle - Handle a verificar (sin @)
     */
    checkHandleAvailability(handle: string): Observable<CheckHandleResponse>;
    private get baseUrl();
    /** Base for /v2/users endpoints (separate from /v2/auth). */
    private get usersBaseUrl();
    private handleSuccessfulAuth;
    private clearState;
    private setupFirestoreRBACSync;
    private _attachFirestoreRBACListener;
    private teardownFirestoreRBACSync;
    private startRefreshTimer;
    private stopRefreshTimer;
    private handleSyncEvent;
    private handleAuthError;
    private signInWithFirebase;
    private signOutFirebase;
    /**
     * Re-establece la sesión de Firebase Auth en el bootstrap de la app cuando
     * el access token de la app sigue válido (la rama de initialize() que NO
     * pasa por refresh).
     *
     * Firebase Auth mantiene su PROPIA sesión con persistencia IndexedDB
     * independiente del storage de tokens de la app. En un navegador normal esa
     * persistencia se auto-restaura sola; en una PWA standalone en iOS el
     * contenedor de storage no sobrevive, y `firebaseAuthReady` se queda en
     * `false` indefinidamente → los listeners Firestore cuelgan (~40s timeout).
     *
     * Estrategia: dar una ventana corta a la auto-restauración de Firebase y, si
     * no ocurre, forzar un `refreshAccessToken()` — que ya hace `signInWithFirebase`
     * con el `firebaseToken` que devuelve `/refresh`.
     *
     * Fire-and-forget: se invoca con `void` para no demorar `initialize()`.
     */
    private ensureFirebaseSessionOnBootstrap;
    /**
     * Fallback self-healing de Firebase Auth. Pide un firebaseToken fresco vía
     * `/refresh` (que sí lo devuelve de forma confiable) y, en éxito,
     * `refreshAccessToken()` ya ejecuta `signInWithFirebase()`.
     *
     * Se invoca cuando un path de auth dejó la sesión de Firebase sin establecer:
     *  - login OAuth/password que volvió sin `firebaseToken`,
     *  - cold launch de PWA iOS sin persistencia de Firebase.
     *
     * `reason` aparece en los logs `[FBAuth] fallback` para poder atestiguar
     * desde el debug-console qué disparó el fallback.
     */
    private reestablishFirebaseViaRefresh;
    /**
     * Solicita permisos de notificación y registra el dispositivo.
     * Usar cuando el usuario acepta recibir notificaciones.
     *
     * @example
     * ```typescript
     * async onEnableNotifications() {
     *   const result = await this.auth.enableNotifications();
     *   if (result.granted) {
     *     console.log('Notificaciones habilitadas');
     *   }
     * }
     * ```
     */
    enableNotifications(): Promise<EnableNotificationsResult>;
    /**
     * Desactiva las notificaciones para este dispositivo.
     * Elimina el token del backend y de FCM.
     * Usar desde un toggle de preferencias cuando el usuario desactiva notificaciones.
     *
     * NOTA: Esto NO revoca el permiso del navegador (el usuario debe hacerlo manualmente
     * desde la configuración del navegador). Solo elimina el registro del dispositivo.
     *
     * @example
     * ```typescript
     * async onToggleNotifications(enabled: boolean) {
     *   if (enabled) {
     *     await this.auth.enableNotifications();
     *   } else {
     *     await this.auth.disableNotifications();
     *   }
     * }
     * ```
     */
    disableNotifications(): Promise<{
        disabled: boolean;
    }>;
    /**
     * Retorna el estado actual de permisos de notificación.
     *
     * @returns 'granted' | 'denied' | 'default' | 'unsupported'
     */
    getNotificationPermissionState(): NotificationPermissionState;
    /**
     * Registra manualmente el dispositivo en el backend.
     * Útil para sincronizar dispositivos que tienen token FCM pero no están registrados.
     *
     * @param providedToken Token FCM opcional. Si se proporciona, se usa directamente
     *                      sin depender del MessagingService (evita timing issues).
     * @returns Resultado del registro con deviceId si fue exitoso
     *
     * @example
     * ```typescript
     * // Sincronizar con token existente (recomendado)
     * const result = await this.auth.registerDevice(myToken);
     *
     * // Sin token, intentará obtenerlo del MessagingService
     * const result = await this.auth.registerDevice();
     * ```
     */
    registerDevice(providedToken?: string): Promise<RegisterDeviceResult>;
    /**
     * Registra el dispositivo en el backend si tiene permisos de notificación.
     * Se llama automáticamente después de un login exitoso si enableDeviceRegistration=true.
     */
    private registerDeviceIfNeeded;
    /**
     * Elimina el dispositivo del backend y borra el token FCM.
     */
    private unregisterDevice;
    /**
     * Detecta información de la plataforma del dispositivo.
     */
    private detectPlatformInfo;
    static ɵfac: i0.ɵɵFactoryDeclaration<AuthService, [{ optional: true; }, null, null, null, null, null, null, null, null, { optional: true; }, { optional: true; }, null, { optional: true; }]>;
    static ɵprov: i0.ɵɵInjectableDeclaration<AuthService>;
}
