import { DecodedAppCheckToken } from 'firebase-admin/app-check';
import { DecodedIdToken } from 'firebase-admin/auth';
import { ContextProvider, RequestData } from 'genkit/context';
import { FirebaseServerApp, FirebaseApp, FirebaseOptions } from 'firebase/app';

/**
 * Copyright 2024 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Debug features that can be enabled to simplify testing.
 * These features are in a JSON object for FIREBASE_DEBUG_FEATURES and only take
 * effect if FIREBASE_DEBUG_MODE=true.
 *
 * Do not set these variables in production.
 */
interface DebugFeatures {
    skipTokenVerification?: boolean;
}
declare function setDebugSkipTokenVerification(skip: boolean): void;
/**
 * The type of data that will be added to an Action's context when using the fireabse middleware.
 * You can safely cast Action's context to a Firebase Context to help type checking and code complete.
 */
interface FirebaseContext {
    /**
     * Information about the authorized user.
     * This comes from the Authentication header, which is a JWT bearer token.
     * Will be omitted if auth is not defined or the key is invalid. To reject requests in these cases
     * set signedIn in a declarative policy or check in a policy callback.
     */
    auth?: {
        uid: string;
        token: DecodedIdToken;
        rawToken: string;
    };
    /**
     * Information about the AppCheck token for a request.
     * This comes form the X-Firebase-AppCheck header and is included in the firebase-functions
     * client libraries (which can be used for Genkit requests irrespective of whether they're hosted
     * on Firebase).
     * Will be omitted if AppCheck tokens are invalid. To reject requests in these cases,
     * set enforceAppCheck in a declaritve policy or check in a policy callback.
     */
    app?: {
        appId: string;
        token: DecodedAppCheckToken;
        alreadyConsumed?: boolean;
        rawToken: string;
    };
    /**
     * An unverified token for a Firebase Instance ID.
     */
    instanceIdToken?: string;
    /**
     * A FirebaseServerApp with the same Auth and App Check credentials as the request.
     */
    firebaseApp?: FirebaseServerApp;
}
interface FirebaseContextProvider<I = any> extends ContextProvider<FirebaseContext, I> {
    (request: RequestData<I>): Promise<FirebaseContext>;
}
/**
 * Helper methods that provide most common needs for an authorization policy.
 */
interface DeclarativePolicy {
    /**
     * Requires the user to be signed in or not.
     * Implicitly part of hasClaims.
     */
    signedIn?: boolean;
    /**
     * Requires the user's email to be verified.
     * Requires the user to be signed in.
     */
    emailVerified?: boolean;
    /**
     * Clam or Claims that must be present in the request.
     * Can be a singel claim name or array of claim names to merely test the presence
     * of a clam or can be an object of claim names and values that must be present.
     * Requires the user to be signed in.
     */
    hasClaim?: string | string[] | Record<string, string>;
    /**
     * Whether appCheck must be enforced
     */
    enforceAppCheck?: boolean;
    /**
     * Whether app check enforcement includes consuming tokens.
     * Consuming tokens adds more security at the cost of performance.
     */
    consumeAppCheckToken?: boolean;
    /**
     * Either a FirebaseApp or the options used to initialize one. When provided,
     * `context.firebaseApp` will be populated as a FirebaseServerApp with the current
     * request's auth and app check credentials allowing you to perform actions using
     * Firebase Client SDKs authenticated as the requesting user.
     *
     * You must have the `firebase` dependency in your `package.json` to use this option.
     */
    serverAppConfig?: FirebaseApp | FirebaseOptions;
}
/**
 * Calling firebaseContext() without any parameters merely parses firebase context data.
 * It does not do any validation on the data found. To do automatic validation,
 * pass either an options object or function for freeform validation.
 */
declare function firebaseContext<I = any>(): FirebaseContextProvider<I>;
/**
 * Calling firebaseContext() with a declarative policy both parses and enforces context.
 * Honors the same environment variables that Cloud Functions for Firebase does to
 * mock token validation in preproduction environmets.
 */
declare function firebaseContext<I = any>(policy: DeclarativePolicy): FirebaseContextProvider<I>;
/**
 * Calling firebaseContext() with a policy callback parses context but delegates enforcement.
 * To control the message sent to a user, throw UserFacingError.
 * For security reasons, other error types will be returned as a 500 "internal error".
 */
declare function firebaseContext<I = any>(policy: (context: FirebaseContext, input: I) => void | Promise<void>): FirebaseContextProvider<I>;
declare function fakeToken(claims: Record<string, string>): string;

export { type DebugFeatures, type DeclarativePolicy, type FirebaseContext, type FirebaseContextProvider, fakeToken, firebaseContext, setDebugSkipTokenVerification };
