/**
 * Scopes supported by the OAuth 2.1 authorization server.
 * Used by better-auth oauthProvider config, well-known endpoints, and consent UI.
 */
export const LLM_PROXY_OAUTH_SCOPE = "llm:proxy";

/**
 * Scope requested by MCP OAuth clients (machine-to-machine / service-account
 * access to MCP gateways via the `client_credentials` grant). Matches the scope
 * advertised in the protected-resource-metadata document.
 */
export const MCP_GATEWAY_OAUTH_SCOPE = "mcp";

/**
 * Standard OIDC offline-access scope. Requested by authorization_code MCP OAuth
 * clients so the token endpoint issues a refresh token for long-running servers.
 */
export const OFFLINE_ACCESS_OAUTH_SCOPE = "offline_access";

export const OAUTH_SCOPES = [
  MCP_GATEWAY_OAUTH_SCOPE,
  LLM_PROXY_OAUTH_SCOPE,
  "openid",
  "profile",
  "email",
  OFFLINE_ACCESS_OAUTH_SCOPE,
] as const;
export type OAuthScope = (typeof OAUTH_SCOPES)[number];

/**
 * Human-readable descriptions for each OAuth scope.
 * Used by the consent page to explain what each scope grants.
 */
export const OAUTH_SCOPE_DESCRIPTIONS: Record<OAuthScope, string> = {
  mcp: "Access MCP tools and resources",
  "llm:proxy": "Access LLM proxy endpoints",
  openid: "Verify your identity",
  profile: "Access your profile information",
  email: "Access your email address",
  offline_access: "Maintain access when you're not present",
};

/**
 * OAuth 2.1 endpoint paths (relative to base URL).
 * These are served by better-auth and proxied through the frontend catch-all.
 */
export const OAUTH_ENDPOINTS = {
  authorize: "/api/auth/oauth2/authorize",
  token: "/api/auth/oauth2/token",
  register: "/api/auth/oauth2/register",
  jwks: "/api/auth/jwks",
  consent: "/api/auth/oauth2/consent",
} as const;

/**
 * Issuer-root aliases for the OAuth 2.1 endpoints.
 *
 * RFC 8414 (OAuth 2.0 Authorization Server Metadata) lets a client discover the
 * real endpoint locations from `/.well-known/oauth-authorization-server`, so a
 * client that performs discovery always uses the canonical {@link OAUTH_ENDPOINTS}
 * paths advertised in that metadata. A client that *skips* discovery — e.g. one
 * configured manually with "bring your own credentials", given only an issuer or
 * token URL — instead falls back to the conventional issuer-relative paths that
 * RFC 6749 uses throughout its examples: the authorization endpoint at
 * `/authorize` (RFC 6749 Section 3.1) and the token endpoint at `/token`
 * (RFC 6749 Section 3.2), plus `/register` for Dynamic Client Registration
 * (RFC 7591 Section 3). Because our authorization server (better-auth) mounts
 * those endpoints under `/api/auth/oauth2/*`, we alias each conventional root
 * path onto its canonical endpoint so non-discovering clients reach the right
 * handler instead of a 404.
 *
 * `jwks` is intentionally omitted: it is never guessed at a conventional path,
 * only ever dereferenced via the `jwks_uri` value published in the metadata
 * (RFC 8414 Section 2), so there is no root path for a client to fall back to.
 */
export const OAUTH_ISSUER_ROOT_ALIASES: ReadonlyArray<{
  root: string;
  canonical: string;
}> = [
  { root: "/authorize", canonical: OAUTH_ENDPOINTS.authorize },
  { root: "/token", canonical: OAUTH_ENDPOINTS.token },
  { root: "/register", canonical: OAUTH_ENDPOINTS.register },
];

/**
 * OAuth 2.1 page paths (frontend routes).
 */
export const OAUTH_PAGES = {
  login: "/auth/sign-in",
  consent: "/oauth/consent",
} as const;

/**
 * Prefix for OAuth-derived token IDs in TokenAuthResult.
 * Used when constructing tokenId from OAuth access tokens (e.g. `oauth-${accessToken.id}`)
 * and when detecting OAuth auth method from tokenId.
 */
export const OAUTH_TOKEN_ID_PREFIX = "oauth-";

/**
 * clientId prefix for MCP OAuth clients. Used to route the `client_credentials`
 * grant at the token endpoint to the MCP issuer (vs. the LLM proxy issuer).
 */
export const MCP_OAUTH_CLIENT_ID_PREFIX = "mcp_oauth_";

/**
 * referenceId prefix that binds a client_credentials access token to the MCP
 * OAuth client that minted it. The MCP gateway validator keys its
 * service-account authorization branch on this prefix. Distinct from
 * `mcp-resource:` (per-profile enterprise-managed binding) so the existing
 * audience check passes through to the service-account branch.
 */
export const MCP_OAUTH_CLIENT_REFERENCE_PREFIX = "mcp-oauth-client:";

/**
 * referenceId prefix that binds an access token to a single shareable MCP App
 * connector, suffixed with the connector's canonical resource URI
 * (`https://host/api/mcp/app/<appId>`, RFC 8707). The connector accepts a token
 * only when this binding matches its own canonical URI; every other OAuth
 * resource validator rejects this prefix. Distinct from `mcp-resource:`
 * (per-profile, enterprise-managed) and `mcp-oauth-client:` (service account).
 * The `mcp` scope is coarse, so this binding is the sole per-connector
 * isolation — it is load-bearing.
 */
export const MCP_APP_RESOURCE_REFERENCE_PREFIX = "mcp-app-resource:";

/**
 * Path for deep-linking to MCP catalog install dialogs.
 * Used by backend error messages and frontend routing.
 * Append `?install={catalogId}` to auto-open the install dialog.
 */
export const MCP_CATALOG_INSTALL_PATH = "/mcp/registry";
export const MCP_CATALOG_INSTALL_QUERY_PARAM = "install";

/**
 * Optional companions to `?install={catalogId}` for pre-targeting the
 * connection: `&scope=personal|team|org` and, for team scope, `&team={teamId}`.
 * Used by the catalog item detail page's add-connection actions, which hand
 * off to the registry page's install flow.
 */
export const MCP_CATALOG_INSTALL_SCOPE_QUERY_PARAM = "scope";
export const MCP_CATALOG_INSTALL_TEAM_QUERY_PARAM = "team";

/**
 * Query params for deep-linking to the re-authentication dialog.
 * Append `?reauth={catalogId}&server={mcpServerId}` to auto-open
 * the credential dialog for in-place re-authentication.
 */
export const MCP_CATALOG_REAUTH_QUERY_PARAM = "reauth";
export const MCP_CATALOG_SERVER_QUERY_PARAM = "server";

/**
 * Query param for deep-linking to a catalog item's edit dialog.
 * Append `?edit={catalogId}` to auto-open the editor. Unlike the install/reauth
 * params, this one persists while the dialog is open so the URL stays
 * shareable. Only users who can edit the item see the editor; others get an
 * access-denied message, and unknown/invisible ids are silently ignored.
 */
export const MCP_CATALOG_EDIT_QUERY_PARAM = "edit";

/**
 * Query param for deep-linking to the catalog "Add MCP Server" dialog
 * pre-filled from an existing item. Append `?clone={catalogId}` to open the
 * create dialog with the item's configuration cloned. Used by the catalog
 * item detail page, which has no create dialog of its own.
 */
export const MCP_CATALOG_CLONE_QUERY_PARAM = "clone";
