import { Awaitable, LiteralString } from "../types/helper.mjs";
//#region src/oauth2/oauth-provider.d.ts
interface OAuth2Tokens {
  tokenType?: string | undefined;
  accessToken?: string | undefined;
  refreshToken?: string | undefined;
  accessTokenExpiresAt?: Date | undefined;
  refreshTokenExpiresAt?: Date | undefined;
  scopes?: string[] | undefined;
  idToken?: string | undefined;
  /**
   * Raw token response from the provider.
   * Preserves provider-specific fields that are not part of the standard OAuth2 token response.
   */
  raw?: Record<string, unknown> | undefined;
}
type OAuth2UserInfo = {
  id: string | number;
  name?: string | undefined;
  email?: (string | null) | undefined;
  image?: string | undefined;
  emailVerified: boolean;
};
interface OAuthProvider<T extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Partial<ProviderOptions>> {
  id: LiteralString;
  createAuthorizationURL: (data: {
    state: string;
    codeVerifier: string;
    scopes?: string[] | undefined;
    redirectURI: string;
    display?: string | undefined;
    loginHint?: string | undefined;
  }) => Awaitable<URL>;
  name: string;
  validateAuthorizationCode: (data: {
    code: string;
    redirectURI: string;
    codeVerifier?: string | undefined;
    deviceId?: string | undefined;
  }) => Promise<OAuth2Tokens | null>;
  getUserInfo: (token: OAuth2Tokens & {
    /**
     * The user object from the provider
     * This is only available for some providers like Apple
     */
    user?: {
      name?: {
        firstName?: string;
        lastName?: string;
      };
      email?: string;
    } | undefined;
  }) => Promise<{
    user: OAuth2UserInfo;
    data: T;
  } | null>;
  /**
   * Custom function to refresh a token
   */
  refreshAccessToken?: ((refreshToken: string) => Promise<OAuth2Tokens>) | undefined;
  revokeToken?: ((token: string) => Promise<void>) | undefined;
  /**
   * Verify the id token
   * @param token - The id token
   * @param nonce - The nonce
   * @returns True if the id token is valid, false otherwise
   */
  verifyIdToken?: ((token: string, nonce?: string) => Promise<boolean>) | undefined;
  /**
   * Disable implicit sign up for new users. When set to true for the provider,
   * sign-in need to be called with with requestSignUp as true to create new users.
   */
  disableImplicitSignUp?: boolean | undefined;
  /**
   * Disable sign up for new users.
   */
  disableSignUp?: boolean | undefined;
  /**
   * Options for the provider
   */
  options?: O | undefined;
}
type ProviderOptions<Profile extends Record<string, any> = any> = {
  /**
   * The client ID of your application.
   *
   * This is usually a string but can be any type depending on the provider.
   */
  clientId?: unknown | undefined;
  /**
   * The client secret of your application
   */
  clientSecret?: string | undefined;
  /**
   * The scopes you want to request from the provider
   */
  scope?: string[] | undefined;
  /**
   * Remove default scopes of the provider
   */
  disableDefaultScope?: boolean | undefined;
  /**
   * The redirect URL for your application. This is where the provider will
   * redirect the user after the sign in process. Make sure this URL is
   * whitelisted in the provider's dashboard.
   */
  redirectURI?: string | undefined;
  /**
   * Custom authorization endpoint URL.
   * Use this to override the default authorization endpoint of the provider.
   * Useful for testing with local OAuth servers or using sandbox environments.
   */
  authorizationEndpoint?: string | undefined;
  /**
   * The client key of your application
   * Tiktok Social Provider uses this field instead of clientId
   */
  clientKey?: string | undefined;
  /**
   * Disable provider from allowing users to sign in
   * with this provider with an id token sent from the
   * client.
   */
  disableIdTokenSignIn?: boolean | undefined;
  /**
   * verifyIdToken function to verify the id token
   */
  verifyIdToken?: ((token: string, nonce?: string) => Promise<boolean>) | undefined;
  /**
   * Custom function to get user info from the provider
   */
  getUserInfo?: ((token: OAuth2Tokens) => Promise<{
    user: {
      id: string;
      name?: string;
      email?: string | null;
      image?: string;
      emailVerified: boolean;
      [key: string]: any;
    };
    data: any;
  } | null>) | undefined;
  /**
   * Custom function to refresh a token
   */
  refreshAccessToken?: ((refreshToken: string) => Promise<OAuth2Tokens>) | undefined;
  /**
   * Custom function to map the provider profile to a
   * user.
   */
  mapProfileToUser?: ((profile: Profile) => {
    id?: string;
    name?: string;
    email?: string | null;
    image?: string;
    emailVerified?: boolean;
    [key: string]: any;
  } | Promise<{
    id?: string;
    name?: string;
    email?: string | null;
    image?: string;
    emailVerified?: boolean;
    [key: string]: any;
  }>) | undefined;
  /**
   * Disable implicit sign up for new users. When set to true for the provider,
   * sign-in need to be called with with requestSignUp as true to create new users.
   */
  disableImplicitSignUp?: boolean | undefined;
  /**
   * Disable sign up for new users.
   */
  disableSignUp?: boolean | undefined;
  /**
   * The prompt to use for the authorization code request
   */
  prompt?: ("select_account" | "consent" | "login" | "none" | "select_account consent") | undefined;
  /**
   * The response mode to use for the authorization code request
   */
  responseMode?: ("query" | "form_post") | undefined;
  /**
   * If enabled, the user info will be overridden with the provider user info
   * This is useful if you want to use the provider user info to update the user info
   *
   * @default false
   */
  overrideUserInfoOnSignIn?: boolean | undefined;
};
//#endregion
export { OAuth2Tokens, OAuth2UserInfo, OAuthProvider, ProviderOptions };