import * as React$1 from 'react';
import React__default, { MutableRefObject, ReactNode } from 'react';
import * as consola from 'consola';
import { z } from 'zod';

/**
 * Auth-related constants shared across the frontend.
 * Single source of truth — do not redefine these elsewhere.
 */
declare const AUTH_CONSTANTS: {
    /** Email OTP code length (numeric). */
    readonly EMAIL_OTP_LENGTH: 4;
    /** TOTP code length (RFC 6238 — authenticator apps). */
    readonly TOTP_LENGTH: 6;
    /** Backup code max length. */
    readonly BACKUP_CODE_MAX_LENGTH: 12;
};

type SessionStatus = 'authenticated' | 'anonymous';
type SessionSnapshot = {
    /** 'authenticated' = a live access token OR a live refresh token exists. */
    status: SessionStatus;
    /** ms-epoch expiry of the current access token (null: no token / no exp). */
    accessExpiresAt: number | null;
};

/**
 * Nested serializer for Centrifugo WebSocket connection token.
 */
type CentrifugoToken = {
    /**
     * JWT token for Centrifugo WebSocket connection
     */
    token: string;
    /**
     * Centrifugo WebSocket URL
     */
    centrifugo_url: string;
    /**
     * Token expiration time (ISO 8601)
     */
    expires_at: string;
    /**
     * List of allowed channels for this user
     */
    channels: Array<string>;
};
/**
 * Serializer for updating user profile.
 */
type CfgUserUpdateRequest = {
    first_name?: string;
    last_name?: string;
    company?: string;
    phone?: string;
    position?: string;
    language?: string;
    /**
     * IANA timezone name (e.g. 'Asia/Seoul'). Auto-detected from browser via X-Timezone header.
     */
    timezone?: string;
};
/**
 * Serializer for OTP request.
 */
type OtpRequestRequest = {
    /**
     * Email address for OTP delivery
     */
    identifier: string;
    /**
     * Source URL for tracking registration (e.g., https://my.djangocfg.com)
     */
    source_url?: string;
};
/**
 * OTP request response.
 */
type OtpRequestResponse = {
    /**
     * Success message
     */
    message: string;
    /**
     * Webmail deep-link for the recipient's provider, or null if the domain is unknown.
     */
    webmail?: WebmailLink | null;
};
/**
 * Serializer for OTP verification.
 */
type OtpVerifyRequest = {
    /**
     * Email address used for OTP request
     */
    identifier: string;
    otp: string;
    /**
     * Source URL for tracking login (e.g., https://my.djangocfg.com)
     */
    source_url?: string;
};
/**
 * OTP verification response.
 *
 * When 2FA is required:
 * - requires_2fa: True
 * - session_id: UUID of 2FA verification session
 * - refresh/access/user: null
 *
 * When 2FA is not required:
 * - requires_2fa: False
 * - session_id: null
 * - refresh/access/user: populated
 */
type OtpVerifyResponse = {
    /**
     * Whether 2FA verification is required
     */
    requires_2fa?: boolean;
    /**
     * 2FA session ID (if requires_2fa is True)
     */
    session_id?: string | null;
    /**
     * JWT refresh token (if requires_2fa is False)
     */
    refresh?: string | null;
    /**
     * JWT access token (if requires_2fa is False)
     */
    access?: string | null;
    /**
     * User information (if requires_2fa is False)
     */
    user?: User | null;
    /**
     * Whether user should be prompted to enable 2FA
     */
    should_prompt_2fa?: boolean;
};
/**
 * Serializer for updating user profile.
 */
type PatchedCfgUserUpdateRequest = {
    first_name?: string;
    last_name?: string;
    company?: string;
    phone?: string;
    position?: string;
    language?: string;
    /**
     * IANA timezone name (e.g. 'Asia/Seoul'). Auto-detected from browser via X-Timezone header.
     */
    timezone?: string;
};
/**
 * Serializer for user details.
 */
type User = {
    readonly id: number;
    readonly email: string;
    first_name?: string | null;
    last_name?: string | null;
    /**
     * Get user's full name.
     */
    readonly full_name: string;
    /**
     * Get user's initials for avatar fallback.
     */
    readonly initials: string;
    /**
     * Get formatted username for display.
     */
    readonly display_username: string;
    company?: string | null;
    phone?: string | null;
    position?: string | null;
    language?: string | null;
    timezone?: string | null;
    readonly avatar: string | null;
    /**
     * Staff status
     *
     * Designates whether the user can log into this admin site.
     */
    readonly is_staff: boolean;
    /**
     * Superuser status
     *
     * Designates that this user has all permissions without explicitly assigning them.
     */
    readonly is_superuser: boolean;
    readonly date_joined: string;
    readonly last_login: string | null;
    readonly unanswered_messages_count: number;
    readonly centrifugo: CentrifugoToken | null;
    readonly api_key: string | null;
};
/**
 * Deep-link that opens the user's webmail on a search for our login email.
 *
 * Present only when the recipient's email domain maps to a known webmail
 * provider (Gmail, Outlook, Mail.ru, Yandex, iCloud, …). For unknown/corporate
 * domains this whole object is null and the frontend shows no button.
 */
type WebmailLink = {
    /**
     * Provider slug (e.g. 'gmail', 'outlook', 'mail_ru'). Also selects the brand icon on the frontend.
     *
     * * `gmail` - gmail
     * * `outlook` - outlook
     * * `yahoo` - yahoo
     * * `icloud` - icloud
     * * `proton` - proton
     * * `zoho` - zoho
     * * `aol` - aol
     * * `fastmail` - fastmail
     * * `gmx` - gmx
     * * `mailcom` - mailcom
     * * `mail_ru` - mail_ru
     * * `yandex` - yandex
     * * `rambler` - rambler
     * * `qq` - qq
     * * `netease` - netease
     * * `sina` - sina
     * * `aliyun` - aliyun
     * * `naver` - naver
     * * `daum` - daum
     * * `web_de` - web_de
     * * `tonline` - tonline
     * * `seznam` - seznam
     * * `wp_pl` - wp_pl
     * * `o2_pl` - o2_pl
     * * `interia` - interia
     * * `libero` - libero
     * * `virgilio` - virgilio
     * * `orange` - orange
     * * `laposte` - laposte
     * * `free_fr` - free_fr
     * * `sfr` - sfr
     */
    provider: WebmailLinkProviderEnum;
    /**
     * Human-facing provider name, e.g. 'Gmail'.
     */
    provider_name: string;
    /**
     * Absolute URL to open in a new tab (a sender-filtered search, or the inbox as fallback).
     */
    url: string;
    /**
     * True if the URL opens a search filtered to our sender; False if it only opens the inbox.
     */
    is_search: boolean;
};
/**
 * * `gmail` - gmail
 * * `outlook` - outlook
 * * `yahoo` - yahoo
 * * `icloud` - icloud
 * * `proton` - proton
 * * `zoho` - zoho
 * * `aol` - aol
 * * `fastmail` - fastmail
 * * `gmx` - gmx
 * * `mailcom` - mailcom
 * * `mail_ru` - mail_ru
 * * `yandex` - yandex
 * * `rambler` - rambler
 * * `qq` - qq
 * * `netease` - netease
 * * `sina` - sina
 * * `aliyun` - aliyun
 * * `naver` - naver
 * * `daum` - daum
 * * `web_de` - web_de
 * * `tonline` - tonline
 * * `seznam` - seznam
 * * `wp_pl` - wp_pl
 * * `o2_pl` - o2_pl
 * * `interia` - interia
 * * `libero` - libero
 * * `virgilio` - virgilio
 * * `orange` - orange
 * * `laposte` - laposte
 * * `free_fr` - free_fr
 * * `sfr` - sfr
 */
declare enum WebmailLinkProviderEnum {
    GMAIL = "gmail",
    OUTLOOK = "outlook",
    YAHOO = "yahoo",
    ICLOUD = "icloud",
    PROTON = "proton",
    ZOHO = "zoho",
    AOL = "aol",
    FASTMAIL = "fastmail",
    GMX = "gmx",
    MAILCOM = "mailcom",
    MAIL_RU = "mail_ru",
    YANDEX = "yandex",
    RAMBLER = "rambler",
    QQ = "qq",
    NETEASE = "netease",
    SINA = "sina",
    ALIYUN = "aliyun",
    NAVER = "naver",
    DAUM = "daum",
    WEB_DE = "web_de",
    TONLINE = "tonline",
    SEZNAM = "seznam",
    WP_PL = "wp_pl",
    O2_PL = "o2_pl",
    INTERIA = "interia",
    LIBERO = "libero",
    VIRGILIO = "virgilio",
    ORANGE = "orange",
    LAPOSTE = "laposte",
    FREE_FR = "free_fr",
    SFR = "sfr"
}

/**
 * Auth Form Types
 *
 * Single source of truth for auth form state and handlers.
 * Used by both @djangocfg/api/auth hooks and @djangocfg/layouts/AuthLayout.
 */

type AuthStep = 'identifier' | 'otp' | '2fa' | '2fa-setup' | 'success';
interface OTPRequestResult {
    success: boolean;
    message: string;
    statusCode?: number;
    retryAfter?: number;
    /** Webmail deep-link for the recipient's provider, or null if unknown. */
    webmail?: WebmailLink | null;
}
interface AuthFormState {
    /** Email address */
    identifier: string;
    /** OTP code input */
    otp: string;
    /** Loading state */
    isLoading: boolean;
    /** Terms acceptance state */
    acceptedTerms: boolean;
    /** Current form step */
    step: AuthStep;
    /** Error message */
    error: string;
    /** 2FA session ID from OTP/OAuth verification */
    twoFactorSessionId: string | null;
    /** Whether user should be prompted to enable 2FA */
    shouldPrompt2FA: boolean;
    /** 2FA code input */
    twoFactorCode: string;
    /** Using backup code instead of TOTP */
    useBackupCode: boolean;
    /** Seconds remaining until rate limit lifts (0 = not rate limited) */
    rateLimitSeconds: number;
    /** True when rateLimitSeconds > 0 — submit should be disabled */
    isRateLimited: boolean;
    /** Formatted countdown label, e.g. "19:00" or "42s" */
    rateLimitLabel: string;
    /** Webmail deep-link for the current identifier's provider (null = no button). */
    webmail: WebmailLink | null;
}
interface AuthFormStateHandlers {
    setIdentifier: (identifier: string) => void;
    setOtp: (otp: string) => void;
    setAcceptedTerms: (accepted: boolean) => void;
    setError: (error: string) => void;
    clearError: () => void;
    setStep: (step: AuthStep) => void;
    setIsLoading: (loading: boolean) => void;
    setTwoFactorSessionId: (sessionId: string | null) => void;
    setShouldPrompt2FA: (prompt: boolean) => void;
    setTwoFactorCode: (code: string) => void;
    setUseBackupCode: (useBackup: boolean) => void;
    /** Start a countdown timer that disables submit for `seconds` seconds */
    startRateLimitCountdown: (seconds: number) => void;
    /** Set (or clear) the webmail deep-link for the current identifier */
    setWebmail: (webmail: WebmailLink | null) => void;
}
interface AuthFormSubmitHandlers {
    handleIdentifierSubmit: (e: React.FormEvent) => Promise<void>;
    handleOTPSubmit: (e: React.FormEvent) => Promise<void>;
    handleResendOTP: () => Promise<void>;
    handleBackToIdentifier: () => void;
    forceOTPStep: () => void;
    /** Handle 2FA TOTP/backup code verification */
    handle2FASubmit: (e: React.FormEvent) => Promise<void>;
    /** Switch to backup code input */
    handleUseBackupCode: () => void;
    /** Switch back to TOTP input */
    handleUseTOTP: () => void;
}
interface AuthFormValidation {
    /** Validate identifier format */
    validateIdentifier: (identifier: string) => boolean;
}
interface AuthFormAutoSubmit {
    /** Ref to track if auto-submit from URL is in progress */
    isAutoSubmittingFromUrl: MutableRefObject<boolean>;
}
interface AuthForm2FAState {
    /** Loading state for 2FA verification */
    is2FALoading: boolean;
    /** Warning message from 2FA (e.g., low backup codes) */
    twoFactorWarning: string | null;
    /** Remaining attempts before 2FA lockout (null = unknown) */
    twoFactorAttemptsRemaining: number | null;
}
interface AuthFormReturn extends AuthFormState, AuthFormStateHandlers, AuthFormSubmitHandlers, AuthFormValidation, AuthFormAutoSubmit, AuthForm2FAState {
}
interface UseAuthFormOptions {
    /** Callback when identifier step succeeds */
    onIdentifierSuccess?: (identifier: string) => void;
    /** Callback when OTP verification succeeds */
    onOTPSuccess?: () => void;
    /** Callback on any error */
    onError?: (message: string) => void;
    /** Source URL for tracking */
    sourceUrl: string;
    /** URL to redirect after successful OTP verification */
    redirectUrl?: string;
    /** If true, user must accept terms before submitting. Default: false */
    requireTermsAcceptance?: boolean;
    /** Path to auth page for auto-OTP detection. Default: '/auth' */
    authPath?: string;
}

type UserProfile = User;
interface AuthConfig {
    apiUrl?: string;
    routes?: {
        auth?: string;
        defaultCallback?: string;
        defaultAuthCallback?: string;
    };
    onLogout?: () => void;
}
/**
 * AuthConfig.routes resolved against the framework conventions — no field is
 * optional here. This is what components consume (via `useAuth().routes`)
 * instead of defaulting to route constants themselves.
 */
interface ResolvedAuthRoutes {
    auth: string;
    defaultCallback: string;
    defaultAuthCallback: string;
}
interface AuthContextType {
    user: UserProfile | null;
    isLoading: boolean;
    isAuthenticated: boolean;
    isAdminUser: boolean;
    /** Resolved route conventions (config override or framework default). */
    routes: ResolvedAuthRoutes;
    loadCurrentProfile: (callerId?: string) => Promise<void>;
    checkAuthAndRedirect: () => Promise<void>;
    getToken: () => string | null;
    getRefreshToken: () => string | null;
    getSavedEmail: () => string | null;
    saveEmail: (email: string) => void;
    clearSavedEmail: () => void;
    requestOTP: (identifier: string, sourceUrl?: string) => Promise<OTPRequestResult>;
    verifyOTP: (identifier: string, otpCode: string, sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean) => Promise<{
        success: boolean;
        message: string;
        user?: UserProfile;
        requires_2fa?: boolean;
        session_id?: string | null;
        should_prompt_2fa?: boolean;
    }>;
    refreshToken: () => Promise<{
        success: boolean;
        message: string;
    }>;
    logout: () => void;
    saveRedirectUrl: (url: string) => void;
    getRedirectUrl: () => string;
    clearRedirectUrl: () => void;
    hasRedirectUrl: () => boolean;
    updateProfile: (data: {
        first_name?: string;
        last_name?: string;
        username?: string;
    }) => Promise<UserProfile>;
    uploadAvatar: (avatar: File | Blob) => Promise<UserProfile>;
}
interface AuthProviderProps {
    children: React__default.ReactNode;
    config?: AuthConfig;
    /** Set false to skip all auth logic and render children directly. */
    enabled?: boolean;
}

declare const AuthContext: React__default.Context<AuthContextType>;
/**
 * AuthProvider — wraps AccountsProvider + AuthProviderInternal.
 *
 * Memoised: re-renders only when `config` reference or `children` change.
 */
declare function AuthProviderRaw({ children, config, enabled }: AuthProviderProps): React__default.JSX.Element;
declare const AuthProvider: React__default.MemoExoticComponent<typeof AuthProviderRaw>;
/**
 * Hook to access auth context.
 *
 * SSR-safe: returns default unauthenticated state when called outside
 * AuthProvider (e.g. during static page generation).
 */
declare const useAuth: () => AuthContextType;

declare const PatchedCfgUserUpdateRequestSchema: z.ZodObject<{
    first_name: z.ZodOptional<z.ZodString>;
    last_name: z.ZodOptional<z.ZodString>;
    company: z.ZodOptional<z.ZodString>;
    phone: z.ZodOptional<z.ZodString>;
    position: z.ZodOptional<z.ZodString>;
    language: z.ZodOptional<z.ZodString>;
    timezone: z.ZodOptional<z.ZodString>;
}, z.core.$strip>;

interface AccountsContextValue {
    profile?: User;
    isLoadingProfile: boolean;
    profileError: Error | null;
    updateProfile: (data: CfgUserUpdateRequest) => Promise<User>;
    partialUpdateProfile: (data: PatchedCfgUserUpdateRequest) => Promise<User>;
    uploadAvatar: (avatar: File | Blob) => Promise<User>;
    refreshProfile: (options?: {
        callerId?: string;
        force?: boolean;
    }) => Promise<User | undefined>;
    requestOTP: (data: OtpRequestRequest) => Promise<OtpRequestResponse>;
    verifyOTP: (data: OtpVerifyRequest) => Promise<OtpVerifyResponse>;
    logout: () => void;
}
interface AccountsProviderProps {
    children: ReactNode;
}
declare function AccountsProvider({ children }: AccountsProviderProps): React$1.JSX.Element;
declare function useAccountsContext(): AccountsContextValue;

declare function useSession(): SessionSnapshot;

/**
 * Universal Router Hook with BasePath Support
 *
 * Wrapper around Next.js useRouter that automatically handles basePath
 * for static builds served via iframe or subdirectory
 *
 * IMPORTANT: In Next.js 15 App Router, router.push() does NOT automatically
 * handle basePath (unlike Pages Router). This is a breaking change in App Router.
 *
 * This hook ensures basePath is always included when navigating, especially
 * important for static exports served via iframe where basePath is critical.
 *
 * @see https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration
 */
/**
 * Router with basePath support
 *
 * Automatically adds basePath to all navigation methods when basePath is configured.
 * In Next.js 15 App Router, router.push() doesn't handle basePath automatically,
 * so this hook uses window.location to ensure basePath is always included.
 *
 * @example
 * ```tsx
 * const router = useCfgRouter();
 *
 * // With basePath='/cfg/admin':
 * router.push('/dashboard');     // Client-side navigation to '/cfg/admin/dashboard'
 * router.replace('/auth');       // Client-side replace with '/cfg/admin/auth'
 * router.hardPush('/dashboard'); // Full page reload to '/cfg/admin/dashboard'
 * router.hardReplace('/auth');   // Full page replace with '/cfg/admin/auth'
 * ```
 */
declare function useCfgRouter(): {
    push: (href: string, options?: {
        scroll?: boolean;
    }) => void;
    replace: (href: string, options?: {
        scroll?: boolean;
    }) => void;
    hardPush: (href: string) => void;
    hardReplace: (href: string) => void;
    prefetch: (href: string) => void;
    back: () => void;
    forward: () => void;
    refresh: () => void;
};

/**
 * useQueryParams Hook
 *
 * Safe hook to access URL query parameters without requiring Suspense boundary.
 * Works on client-side only, returns empty URLSearchParams during SSR/prerendering.
 *
 * @example
 * ```tsx
 * const params = useQueryParams();
 * const flow = params.get('flow');
 * const hasFlow = params.has('flow');
 * const allTags = params.getAll('tags');
 * ```
 */
/**
 * Hook to safely access URL query parameters without useSearchParams()
 *
 * This hook reads query parameters directly from window.location.search,
 * avoiding the need for Suspense boundaries that useSearchParams() requires.
 *
 * Automatically updates when URL changes (navigation, back/forward, etc.)
 * Uses pathname from Next.js to detect route changes and polls for query param changes.
 *
 * Returns a URLSearchParams object with get(), getAll(), has(), etc.
 *
 * @returns URLSearchParams object (empty during SSR)
 */
declare function useQueryParams(): URLSearchParams;

interface UseAuthFormStateReturn extends AuthFormState, AuthFormStateHandlers {
}
/**
 * Hook for auth form state management.
 * Pure state - no side effects, no API calls.
 */
declare const useAuthFormState: (initialIdentifier?: string) => UseAuthFormStateReturn;

declare const useAuthValidation: () => AuthFormValidation;
declare const validateIdentifier: (id: string) => boolean;

/**
 * Complete auth form hook.
 * Composes smaller hooks for state, validation, and submission.
 */
declare const useAuthForm: (options: UseAuthFormOptions) => AuthFormReturn;

interface UseAutoAuthOptions {
    /** Called with the OTP from the URL, plus the optional `email` query param if present. */
    onOTPDetected?: (otp: string, email?: string) => void;
    cleanupUrl?: boolean;
    /** Paths where auto-auth should be active. Default: ['/auth'] */
    allowedPaths?: string[];
}
/**
 * Hook for automatic authentication from URL query parameters
 * Detects OTP from URL and triggers callback.
 * (Path normalization / allow-list matching live in ../utils/path so they can
 * be unit-tested independently of the hook.)
 */
declare const useAutoAuth: (options?: UseAutoAuthOptions) => {
    isReady: boolean;
    hasOTP: boolean;
    isAllowedPath: boolean;
};

interface UseGithubAuthOptions {
    sourceUrl?: string;
    onSuccess?: (user: any, isNewUser: boolean) => void;
    onError?: (error: string) => void;
    /** Callback when 2FA is required */
    onRequires2FA?: (sessionId: string, shouldPrompt2FA: boolean) => void;
    redirectUrl?: string;
    /** Skip automatic redirect after success (caller handles navigation) */
    skipRedirect?: boolean;
}
interface UseGithubAuthReturn {
    isLoading: boolean;
    error: string | null;
    startGithubAuth: () => Promise<void>;
    handleGithubCallback: (code: string, state: string) => Promise<void>;
}
/**
 * Hook for GitHub OAuth authentication flow.
 *
 * Usage:
 * 1. Call startGithubAuth() to redirect user to GitHub
 * 2. After GitHub redirects back, call handleGithubCallback(code, state)
 *
 * @example
 * ```tsx
 * const { isLoading, error, startGithubAuth } = useGithubAuth({
 *   onSuccess: (user) => router.push('/dashboard'),
 *   onError: (error) => console.error(error),
 * });
 *
 * <Button onClick={startGithubAuth} disabled={isLoading}>
 *   Continue with GitHub
 * </Button>
 * ```
 */
declare const useGithubAuth: (options?: UseGithubAuthOptions) => UseGithubAuthReturn;

interface UseTwoFactorVerifyOptions {
    /** Callback on successful 2FA verification */
    onSuccess?: (user: any) => void;
    /** Callback on error */
    onError?: (error: string) => void;
    /** URL to redirect after successful verification */
    redirectUrl?: string;
    /** Skip automatic redirect after success (caller handles navigation) */
    skipRedirect?: boolean;
}
interface UseTwoFactorVerifyReturn {
    /** Loading state */
    isLoading: boolean;
    /** Error message */
    error: string | null;
    /** Warning message (e.g., low backup codes) */
    warning: string | null;
    /** Remaining backup codes (if backup code was used) */
    remainingBackupCodes: number | null;
    /** Remaining verification attempts before lockout */
    attemptsRemaining: number | null;
    /** Verify TOTP code */
    verifyTOTP: (sessionId: string, code: string) => Promise<boolean>;
    /** Verify backup code */
    verifyBackupCode: (sessionId: string, backupCode: string) => Promise<boolean>;
    /** Clear error */
    clearError: () => void;
}
/**
 * 2FA verification during login (internal — composed by {@link useTwoFactor}).
 *
 * After OTP/OAuth verification returns requires_2fa=true and a session_id,
 * collect the TOTP (or backup) code and call verifyTOTP/verifyBackupCode to
 * complete authentication.
 */
declare const useTwoFactorVerify: (options?: UseTwoFactorVerifyOptions) => UseTwoFactorVerifyReturn;

interface TwoFactorSetupData {
    /** Device ID to use for confirmation */
    deviceId: string;
    /** Base32-encoded TOTP secret (for manual entry) */
    secret: string;
    /** otpauth:// URI for QR code generation */
    provisioningUri: string;
    /** Base64-encoded QR code image (data URI) */
    qrCodeBase64: string;
    /** Seconds until setup expires */
    expiresIn: number;
}
interface UseTwoFactorSetupOptions {
    /** Callback when setup is confirmed and backup codes are generated */
    onComplete?: (backupCodes: string[]) => void;
    /** Callback on error */
    onError?: (error: string) => void;
}
interface UseTwoFactorSetupReturn {
    /** Loading state */
    isLoading: boolean;
    /** Error message */
    error: string | null;
    /** Setup data (QR code, secret, etc.) */
    setupData: TwoFactorSetupData | null;
    /** Backup codes after confirmation */
    backupCodes: string[] | null;
    /** Warning message about backup codes */
    backupCodesWarning: string | null;
    /** Current setup step */
    setupStep: 'idle' | 'scanning' | 'confirming' | 'complete';
    /** Start 2FA setup - returns QR code data */
    startSetup: (deviceName?: string) => Promise<TwoFactorSetupData | null>;
    /** Confirm setup with TOTP code - returns backup codes */
    confirmSetup: (code: string) => Promise<string[] | null>;
    /** Reset setup state */
    resetSetup: () => void;
    /** Clear error */
    clearError: () => void;
}
/**
 * 2FA setup — enabling TOTP (internal, composed by {@link useTwoFactor}).
 *
 * Flow: startSetup() → user scans QR → confirmSetup(code) → show backup codes.
 */
declare const useTwoFactorSetup: (options?: UseTwoFactorSetupOptions) => UseTwoFactorSetupReturn;

interface TwoFactorDevice {
    id: string;
    name: string;
    createdAt: string;
    lastUsedAt: string | null;
    isPrimary: boolean;
}
interface UseTwoFactorStatusReturn {
    /** Loading state */
    isLoading: boolean;
    /** Error message */
    error: string | null;
    /** Whether 2FA is enabled for user */
    has2FAEnabled: boolean | null;
    /** List of TOTP devices */
    devices: TwoFactorDevice[];
    /** Fetch 2FA status */
    fetchStatus: () => Promise<void>;
    /** Disable 2FA (requires TOTP code) */
    disable2FA: (code: string) => Promise<boolean>;
    /** Clear error */
    clearError: () => void;
}
/**
 * Read and manage 2FA status (internal, composed by {@link useTwoFactor}).
 *
 * Fetches the device list / enabled flag and disables 2FA.
 */
declare const useTwoFactorStatus: () => UseTwoFactorStatusReturn;

interface UseTwoFactorOptions {
    /** Options for the login-time verification namespace */
    verify?: UseTwoFactorVerifyOptions;
    /** Options for the setup (enable) namespace */
    setup?: UseTwoFactorSetupOptions;
}
interface UseTwoFactorReturn {
    /** Verify a 2FA challenge during login (TOTP / backup code). */
    verify: UseTwoFactorVerifyReturn;
    /** Enable 2FA — QR provisioning → confirm → backup codes. */
    setup: UseTwoFactorSetupReturn;
    /** Read device list / enabled flag and disable 2FA. */
    status: UseTwoFactorStatusReturn;
}
/**
 * Single entry point for all two-factor authentication flows.
 *
 * The three concerns — **verify** (login), **setup** (enable) and **status**
 * (manage/disable) — are distinct verbs over the same `CfgTotp*` API, so each
 * is exposed as its own namespace with an independent loading/error surface:
 *
 * @example
 * ```tsx
 * const two = useTwoFactor({ verify: { redirectUrl: '/dashboard' } });
 *
 * await two.verify.verifyTOTP(sessionId, code); // login
 * await two.setup.startSetup('My iPhone');       // enable
 * await two.status.fetchStatus();                // manage
 * ```
 *
 * Consumers that only need one concern can compose the underlying hooks
 * directly (`useTwoFactorVerify` / `useTwoFactorSetup` / `useTwoFactorStatus`),
 * all re-exported alongside this one, to avoid mounting the others' state.
 */
declare const useTwoFactor: (options?: UseTwoFactorOptions) => UseTwoFactorReturn;

interface AuthRedirectOptions {
    fallbackUrl?: string;
    clearOnUse?: boolean;
}
/**
 * Read the saved back-url without clearing it. Null when nothing saved —
 * unlike getFinalRedirectUrl, never substitutes a fallback.
 */
declare const peekSavedRedirect: () => string | null;
/**
 * Read AND clear the saved back-url (single-use intent). Null when nothing
 * saved. This is the one primitive every post-auth navigator uses to honor
 * "return the user to where the guard bounced them from".
 */
declare const consumeSavedRedirect: () => string | null;
declare const useAuthRedirectManager: (options?: AuthRedirectOptions) => {
    redirectUrl: string;
    setRedirect: (url: string) => void;
    getRedirect: () => string;
    clearRedirect: () => void;
    hasRedirect: () => boolean;
    getFinalRedirectUrl: () => string;
    useAndClearRedirect: () => string;
};

/**
 * Simple sessionStorage hook with better error handling
 * @param key - Storage key
 * @param initialValue - Default value if key doesn't exist
 * @returns [value, setValue, removeValue] - Current value, setter function, and remove function
 */
declare function useSessionStorage<T>(key: string, initialValue: T): readonly [T, (value: T | ((val: T) => T)) => void, () => void];

/**
 * Simple localStorage hook with better error handling
 * @param key - Storage key
 * @param initialValue - Default value if key doesn't exist
 * @returns [value, setValue, removeValue] - Current value, setter function, and remove function
 */
declare function useLocalStorage<T>(key: string, initialValue: T): readonly [T, (value: T | ((val: T) => T)) => void, () => void];

/**
 * Encode string to base64
 * @param data - String data to encode
 * @returns Base64 encoded string (or original in dev mode)
 */
declare function encodeBase64(data: string): string;
/**
 * Decode base64 to string
 * @param encoded - Base64 encoded string
 * @returns Decoded string (or original in dev mode)
 */
declare function decodeBase64(encoded: string): string;
/**
 * Hook for base64 encoding/decoding
 * @returns Object with encode and decode functions
 */
declare function useBase64(): {
    encode: typeof encodeBase64;
    decode: typeof decodeBase64;
    isDev: boolean;
};

/**
 * Profile Cache Hook
 *
 * Provides localStorage-based caching for user profile with:
 * - TTL (Time To Live) - default 1 hour
 * - Version control for migrations
 * - Automatic invalidation on expiry
 */

interface ProfileCacheOptions {
    /** Time to live in milliseconds (default: 1 hour) */
    ttl?: number;
}
/**
 * Get cached profile from localStorage
 * @returns User profile if valid cache exists, null otherwise
 */
declare function getCachedProfile(): User | null;
/**
 * Save profile to localStorage cache
 * @param profile - User profile to cache
 * @param options - Cache options (TTL)
 */
declare function setCachedProfile(profile: User, options?: ProfileCacheOptions): void;
/**
 * Clear profile cache from localStorage
 */
declare function clearProfileCache(): void;
/**
 * Check if cached profile is valid (exists and not expired)
 */
declare function hasValidCache(): boolean;
/**
 * Get cache metadata (age, TTL, etc.)
 */
declare function getCacheMetadata(): {
    exists: boolean;
    age?: number;
    ttl?: number;
    expiresIn?: number;
} | null;

interface DeleteAccountResult {
    success: boolean;
    message: string;
}
interface UseDeleteAccountReturn {
    /** Loading state */
    isLoading: boolean;
    /** Error message */
    error: string | null;
    /** Delete the account */
    deleteAccount: () => Promise<DeleteAccountResult>;
    /** Clear error */
    clearError: () => void;
}
/**
 * Hook for deleting user account.
 *
 * This performs a soft delete - deactivates the account and anonymizes personal data.
 * The account can be restored by an administrator if needed.
 *
 * @example
 * ```tsx
 * const { deleteAccount, isLoading, error } = useDeleteAccount();
 *
 * const handleDelete = async () => {
 *   const result = await deleteAccount();
 *   if (result.success) {
 *     // Account deleted, perform logout
 *     await logout();
 *   }
 * };
 * ```
 */
declare const useDeleteAccount: () => UseDeleteAccountReturn;

/**
 * Email validation utility
 */
declare const validateEmail: (email: string) => boolean;

/**
 * Format authentication error for display
 */
declare const formatAuthError: (error: any) => string;

/**
 * Pure auth-guard state resolution.
 *
 * This is the decision that produced the "stuck on Authenticating…" bug: given
 * the auth state, should the UI show a preloader, redirect to login, or render
 * the protected content? Extracted from useAuthGuard (which lives in a package
 * with no test infra) so the branching can be unit-tested in isolation — the
 * hook just wires React state (mounted / isRedirecting) into these functions.
 *
 * Invariant that fixes the bug: once auth is resolved (`authLoading === false`)
 * and the user is unauthenticated, `isLoading` must become false so the guard
 * redirects to the form instead of spinning forever.
 */
interface GuardInput {
    /** First client render matches SSR (preloader) until mounted, to avoid hydration mismatch. */
    mounted: boolean;
    /** Whether this route requires authentication. */
    requireAuth: boolean;
    /** AuthContext still resolving initial state. */
    authLoading: boolean;
    /** A redirect to the auth page is in flight. */
    isRedirecting: boolean;
    /** User currently has a (valid-looking) session. */
    isAuthenticated: boolean;
}
/**
 * True while the guard should render a preloader rather than the protected
 * content. Mirrors useAuthGuard's formula exactly.
 */
declare function resolveGuardIsLoading(s: GuardInput): boolean;
/**
 * Whether the guard should trigger a redirect to the auth page. Only once
 * mounted, on a protected route, after auth resolved, when unauthenticated and
 * not already redirecting. This is the branch that must fire for a dead session.
 */
declare function shouldRedirectToAuth(s: GuardInput): boolean;
/** The effective authenticated flag the guard exposes to consumers. */
declare function resolveGuardIsAuthenticated(s: Pick<GuardInput, 'requireAuth' | 'isAuthenticated'>): boolean;

/**
 * Path normalization for auth routing.
 *
 * next-intl may keep a 2-letter locale prefix in the URL (e.g. `/ru/auth`), and
 * paths arrive with or without trailing slashes. To match a pathname against a
 * fixed allow-list (like `['/auth']`) reliably, strip the locale segment and
 * trailing slashes first. Extracted from useAutoAuth so it can be unit-tested
 * and reused.
 */
/**
 * Strip a leading 2-letter locale segment and trailing slashes.
 * '/ru/auth/' → '/auth', '/auth' → '/auth', '/' → '/', '' → ''.
 */
declare const normalizePath: (path: string | null | undefined) => string;
/**
 * True when `pathname` (after locale/slash normalization) is one of the allowed
 * paths, or nested under one of them (`/auth` matches `/auth/callback`).
 */
declare const isAllowedAuthPath: (pathname: string | null | undefined, allowedPaths: string[]) => boolean;

declare const logger: consola.ConsolaInstance;
/**
 * Auth-specific logger
 */
declare const authLogger: consola.ConsolaInstance;

/**
 * Analytics stub for @djangocfg/api/auth
 * Provides minimal analytics interface without external dependencies
 *
 * If you need full analytics, install @djangocfg/layouts and use its Analytics module
 */
declare enum AnalyticsEvent {
    AUTH_OTP_REQUEST = "auth_otp_request",
    AUTH_LOGIN_SUCCESS = "auth_login_success",
    AUTH_OTP_VERIFY_FAIL = "auth_otp_verify_fail",
    AUTH_SESSION_EXPIRED = "auth_session_expired",
    AUTH_TOKEN_REFRESH = "auth_token_refresh",
    AUTH_TOKEN_REFRESH_FAIL = "auth_token_refresh_fail",
    AUTH_LOGOUT = "auth_logout",
    AUTH_OAUTH_START = "auth_oauth_start",
    AUTH_OAUTH_FAIL = "auth_oauth_fail"
}
declare enum AnalyticsCategory {
    AUTH = "auth"
}
type AnalyticsEventType = `${AnalyticsEvent}`;
type AnalyticsCategoryType = `${AnalyticsCategory}`;
interface AnalyticsEventParams {
    category?: AnalyticsCategoryType;
    label?: string;
    value?: number;
    [key: string]: any;
}
/**
 * Minimal analytics implementation
 * Logs to console in development, silent in production
 */
declare const Analytics: {
    /**
     * Track an analytics event
     */
    event(eventName: AnalyticsEventType, params?: AnalyticsEventParams): void;
    /**
     * Set user ID for tracking
     */
    setUser(userId: string): void;
};

export { AUTH_CONSTANTS, type AccountsContextValue, AccountsProvider, Analytics, AnalyticsCategory, type AnalyticsCategoryType, AnalyticsEvent, type AnalyticsEventType, type AuthConfig, AuthContext, type AuthContextType, type AuthFormAutoSubmit, type AuthFormReturn, type AuthFormState, type AuthFormStateHandlers, type AuthFormSubmitHandlers, type AuthFormValidation, AuthProvider, type AuthProviderProps, type AuthStep, type DeleteAccountResult, type GuardInput, type OTPRequestResult, type PatchedCfgUserUpdateRequest, PatchedCfgUserUpdateRequestSchema, type ProfileCacheOptions, type SessionSnapshot, type SessionStatus, type TwoFactorDevice, type TwoFactorSetupData, type UseAuthFormOptions, type UseAuthFormStateReturn, type UseAutoAuthOptions, type UseDeleteAccountReturn, type UseGithubAuthOptions, type UseGithubAuthReturn, type UseTwoFactorOptions, type UseTwoFactorReturn, type UseTwoFactorSetupOptions, type UseTwoFactorSetupReturn, type UseTwoFactorStatusReturn, type UseTwoFactorVerifyOptions, type UseTwoFactorVerifyReturn, type UserProfile, type WebmailLink, authLogger, clearProfileCache, consumeSavedRedirect, decodeBase64, encodeBase64, formatAuthError, getCacheMetadata, getCachedProfile, hasValidCache, isAllowedAuthPath, logger, normalizePath, peekSavedRedirect, resolveGuardIsAuthenticated, resolveGuardIsLoading, setCachedProfile, shouldRedirectToAuth, useAccountsContext, useAuth, useAuthForm, useAuthFormState, useAuthRedirectManager, useAuthValidation, useAutoAuth, useBase64, useCfgRouter, useDeleteAccount, useGithubAuth, useLocalStorage, useQueryParams, useSession, useSessionStorage, useTwoFactor, useTwoFactorSetup, useTwoFactorStatus, useTwoFactorVerify, validateEmail, validateIdentifier };
