import type { Context } from "hono";
import type { Handler, MiddlewareHandler } from "hono/types";
import type { SignatureAlgorithm } from "hono/utils/jwt/jwa";
import type { SignatureKey } from "hono/utils/jwt/jws";
/** Not-null type */
type NonNull = Record<never, never>;
type AnyRecord<T = unknown> = Record<keyof any, T>;
/** Custom claims for JWT tokens */
type CustomClaims = {
    [key: Exclude<string, "exp">]: NonNull | undefined;
};
/**
 * Metadata for an OpenID Connect Issuer.
 * @template Issuer Union of the const-strings that represent Issuer URLs.
 */
interface AbstractIssuerMetadata<IU extends string> {
    /** OpenID Connect Issuer */
    issuer: IU;
    /** OpenID Connect authentication endpoint */
    authEndpoint: string;
    /** OpenID Connect token endpoint */
    tokenEndpoint: string;
    /** OpenID Connect token revocation endpoint */
    tokenRevocationEndpoint: string;
    /** OpenID Connect client ID */
    clientId: string;
    /** OpenID Connect client secret */
    clientSecret: string;
    /** OpenID Connect scopes */
    scopes: string[];
}
/**
 * Options for local JWT signing.
 */
export interface LocalJwtOptions {
    /** Private key for signing */
    privateKey: SignatureKey;
    /** Signature algorithm */
    alg?: SignatureAlgorithm;
    /** Validity period (in milliseconds) */
    maxAge: number;
}
/**
 * Metadata for an OpenID Connect Issuer.
 * @template I Union of the const-strings that represent Issuer URLs.
 */
export type IssuerMetadata<C extends CustomClaims, IU extends string> = (AbstractIssuerMetadata<IU> & {
    /** Indicates if the Issuer supports refresh tokens */
    useLocalJwt: true;
    /** Options for creating custom JWT when no refresh token is available */
    localJwtOptions: LocalJwtOptions;
    /** Specify how Claims are generated using token and context */
    createClaims: (c: Context, tokens: RefreshTokenGetter) => C | undefined | Promise<C | undefined>;
}) | (AbstractIssuerMetadata<IU> & {
    /** Indicates if the Issuer supports refresh tokens */
    useLocalJwt: false;
    /** Specify how Claims are generated using token and context */
    createClaims: (c: Context, tokens: TokenGetter) => C | undefined | Promise<C | undefined>;
});
/**
 * Options for OpenID Connect.
 * @template C Custom claims for JWT tokens
 * @template IU Union of the const-strings that represent Issuer URLs.
 */
export interface OIDCOptions<C extends CustomClaims, IU extends string> {
    /** Issuer metadata */
    issuers: IssuerMetadata<C, IU>[];
    /** Function to get the Issuer URL */
    getIssUrl: (c: Context) => IU | Promise<IU> | undefined;
    /** Client-side token store */
    clientSideTokenStore: TokenStore;
}
/**
 * Refresh token setter.
 */
interface RefreshTokenSetter {
    setRefreshToken(c: Context, token: string | undefined): void | Promise<void>;
}
/**
 * ID token setter.
 */
interface IDTokenSetter {
    setIDToken(c: Context, token: string | undefined): void | Promise<void>;
}
/**
 * ID token getter.
 */
interface IDTokenGetter {
    getIDToken(c: Context): string | undefined | Promise<string | undefined>;
}
/**
 * Refresh token getter.
 */
interface RefreshTokenGetter {
    getRefreshToken(c: Context): string | undefined | Promise<string | undefined>;
}
/**
 * ID token & refresh token setter.
 */
type TokenSetter = IDTokenSetter & RefreshTokenSetter;
/**
 * ID token & refresh token getter.
 */
type TokenGetter = IDTokenGetter & RefreshTokenGetter;
/**
 * ID token & refresh token getter and setter.
 */
export type TokenStore = TokenGetter & TokenSetter;
/**
 * Get type of OIDC
 */
type OIDCManagerType<T> = T extends OIDCManager<CustomClaims, string> ? T : T extends {
    __oidc: infer U;
} & AnyRecord ? OIDCManagerType<U> : T extends {
    Variables: infer U;
} & AnyRecord ? OIDCManagerType<U> : T extends MiddlewareHandler<infer U> ? OIDCManagerType<U> : T extends OIDCSetupResult<infer C, infer IU> ? OIDCManager<C, IU> : never;
/**
 * Get type of OIDC Custom Claims
 */
export type ClaimsType<T> = OIDCManagerType<T> extends OIDCManager<infer C, string> ? C : T extends IssuerMetadata<infer C, string> ? C : T extends OIDCOptions<infer C, string> ? C : T extends CustomClaims ? T : never;
/**
 * Get type of OIDC Issuer URL
 */
export type IssuerType<T> = OIDCManagerType<T> extends OIDCManager<CustomClaims, infer IU> ? IU : T extends IssuerMetadata<CustomClaims, infer IU> ? IU : T extends OIDCOptions<CustomClaims, infer IU> ? IU : T extends string ? T : never;
export type OIDCMiddlewareType<T> = T extends OIDCMiddleware<CustomClaims> ? T : ClaimsType<T> extends CustomClaims ? OIDCMiddleware<ClaimsType<T>> : never;
type OIDCEnv<C extends CustomClaims> = {
    Variables: {
        claims: C | undefined;
    } & AnyRecord;
};
type OIDCMiddleware<C extends CustomClaims> = MiddlewareHandler<OIDCEnv<C>>;
type OIDCHandler<C extends CustomClaims> = Handler<OIDCEnv<C>>;
/**
 * @template C Custom claims for JWT tokens
 * @template IU Union of the const-strings that represent Issuer URLs.
 * @template P Path parameters
 * @template I Input
 */
export interface OIDCSetupResult<C extends CustomClaims, IU extends string> {
    /**
     * Login handler for OpenID Connect.
     * @param iss Issuer URL
     * @param callback Callback function
     * @returns Handler
     */
    loginHandler: (iss: IU, callback: (res: {
        type: "OK";
        claims: C;
    } | {
        type: "ERR";
        error: "OAuthServerError";
    } | {
        type: "ERR";
        error: "Unauthorized";
    }, ...args: Parameters<OIDCHandler<C>>) => ReturnType<OIDCHandler<C>>) => OIDCHandler<C>;
    /**
     * Middleware to obtain claims from OpenID Connect.
     */
    useClaims: OIDCMiddleware<C>;
    /**
     * Logout handler for OpenID Connect.
     * @param callback Callback function
     * @returns Handler
     */
    logoutHandler: (callback: Handler) => Handler;
}
export declare function OIDC<C extends CustomClaims, IU extends string>(opts: OIDCOptions<C, IU> | ((c: Context) => OIDCOptions<C, IU> | Promise<OIDCOptions<C, IU>>)): OIDCSetupResult<C, IU>;
/**
 * Internal OpenID Connect client.
 * @template C Custom claims for JWT tokens
 * @template IU Union of the const-strings that represent Issuer URLs.
 */
declare class OIDCManager<C extends CustomClaims, IU extends string> {
    #private;
    private constructor();
    /**
     * Create an OIDC client.
     * @param c Context
     * @param opts OIDC options
     * @returns OIDC client
     */
    static create<C extends CustomClaims, IU extends string>(c: Context, opts: OIDCOptions<C, IU>): Promise<OIDCManager<C, IU>>;
    /**
     * Manually Login with OpenID Connect.
     * @param c Context
     * @param issurl OpenID Connect Issuer URL
     * @returns Login result. If the login is successful, the claims are
     * returned.
     */
    login(c: Context, issurl: IU): Promise<{
        type: "OK";
        claims: C;
    } | {
        type: "ERR";
        error: "OAuthServerError";
    } | {
        type: "ERR";
        error: "Unauthorized";
    } | {
        type: "RESPONSE";
        response: Response;
    }>;
    getClaims(c: Context): Promise<C | undefined>;
    logout(c: Context): Promise<void>;
}
export {};
