import type { EventSubscription } from "expo-modules-core";
import { type AuthErrorCode } from "./error";
export type { AuthErrorCode } from "./error";
export { AuthError } from "./error";
export interface SpotifySession {
    /** OAuth access token. */
    accessToken: string;
    /**
     * OAuth refresh token. `null` on Android when no `tokenSwapURL` is provided
     * (the Spotify Android SDK does not expose a refresh token for implicit
     * grants).
     */
    refreshToken: string | null;
    /** Expiration timestamp as Unix epoch milliseconds. */
    expirationDate: number;
    /** Scopes the access token was granted (or requested, on Android implicit). */
    scopes: SpotifyScope[];
}
export type SpotifyScope = "ugc-image-upload" | "user-read-playback-state" | "user-modify-playback-state" | "user-read-currently-playing" | "app-remote-control" | "streaming" | "playlist-read-private" | "playlist-read-collaborative" | "playlist-modify-private" | "playlist-modify-public" | "user-follow-modify" | "user-follow-read" | "user-top-read" | "user-read-recently-played" | "user-library-modify" | "user-library-read" | "user-read-email" | "user-read-private";
export interface AuthenticateConfig {
    /** OAuth scopes to request. Must contain at least one entry. */
    scopes: SpotifyScope[];
    /**
     * If supplied, requests an authorization code rather than an implicit
     * token, then POSTs the code to this URL to exchange it for tokens.
     * **Required on Android** to receive a usable `refreshToken`.
     */
    tokenSwapURL?: string;
    /**
     * Used by the iOS SDK to refresh access tokens automatically, and by
     * `Auth.refresh()` on both platforms.
     */
    tokenRefreshURL?: string;
    /**
     * If `true`, forces Spotify to show the authorization dialog even when the
     * user already has an active session. Defaults to `false`.
     */
    showDialog?: boolean;
}
export interface RefreshConfig {
    /** The refresh token from a previous `Auth.authenticate()` call. */
    refreshToken: string;
    /** URL of your token refresh server endpoint. */
    tokenRefreshURL: string;
    /**
     * Scopes that were granted by the previous session. Used as a fallback when
     * the refresh response omits the `scope` field.
     */
    scopes?: SpotifyScope[];
}
/**
 * Payload delivered to `Auth.addListener("sessionChange", ...)` subscribers.
 */
export type SessionChangeEvent = {
    type: "didInitiate";
    session: SpotifySession;
} | {
    type: "didRenew";
    session: SpotifySession;
} | {
    type: "didFail";
    error: {
        code: AuthErrorCode;
        message: string;
    };
};
/**
 * Spotify Auth namespace. Handles OAuth authentication and session lifecycle.
 *
 * @example
 * ```ts
 * import { Auth } from "@wwdrew/expo-spotify-sdk";
 *
 * const session = await Auth.authenticate({ scopes: ["streaming"] });
 * ```
 */
export declare const Auth: {
    /**
     * Returns `true` if the Spotify app is installed on the device.
     */
    readonly isAvailable: () => boolean;
    /**
     * Starts a Spotify OAuth flow. Resolves with a {@link SpotifySession};
     * rejects with an {@link AuthError} carrying a `code`.
     */
    readonly authenticate: (config: AuthenticateConfig) => Promise<SpotifySession>;
    /**
     * Exchanges a refresh token for a new access token via your token refresh
     * server. Resolves with a fresh {@link SpotifySession}; rejects with an
     * {@link AuthError}.
     */
    readonly refresh: (config: RefreshConfig) => Promise<SpotifySession>;
    /**
     * Forcibly cancel any in-flight `Auth.authenticate()` call. No-op on
     * Android (the Android coordinator self-cleans via structured concurrency).
     *
     * Use before `Auth.authenticate()` to defensively clear any leaked iOS
     * coordinator state (the `SPTSessionManager` delegate callbacks are not
     * guaranteed to fire).
     */
    readonly cancelPending: () => Promise<void>;
    /**
     * Subscribes to session lifecycle events.
     *
     * Events fire for every `Auth.authenticate()` and `Auth.refresh()` call,
     * regardless of whether the call was awaited. Useful for persisting tokens
     * in a central store without coupling the store to the call sites.
     *
     * Returns a `Subscription` — call `.remove()` to unsubscribe.
     *
     * @example
     * ```ts
     * const sub = Auth.addListener("sessionChange", (event) => {
     *   if (event.type === "didInitiate" || event.type === "didRenew") {
     *     store.setSession(event.session);
     *   }
     * });
     * // later:
     * sub.remove();
     * ```
     */
    readonly addListener: (event: "sessionChange", listener: (event: SessionChangeEvent) => void) => EventSubscription;
};
//# sourceMappingURL=index.d.ts.map