// lib/oauth/provider-registry.js — declarative OAuth2 provider catalog.
//
// Each provider is INERT DATA: authorize/token endpoints, default scopes, and
// whether PKCE is used. NO secrets live here — client id/secret are supplied by
// the operator once (per connection) and referenced from the vault by name.
//
// This registry is the single source of truth for "how do I talk to provider X's
// OAuth endpoints". A connection manifest's `oauth.provider` keys into it; the
// manifest may also override authorize_url/token_url/scopes inline so Tool-Smith
// connectors for not-yet-catalogued providers still work without editing code.
//
// Pure ESM — no DB, fs, or network imports.

const PROVIDERS = {
  google: {
    label: 'Google',
    authorize_url: 'https://accounts.google.com/o/oauth2/v2/auth',
    token_url: 'https://oauth2.googleapis.com/token',
    pkce: true,
    // Default to read-only mail+calendar scopes; connections add what they need.
    default_scopes: ['openid', 'email'],
    // Google requires these to mint a refresh token.
    extra_auth_params: { access_type: 'offline', prompt: 'consent' },
  },
  meta: {
    label: 'Meta (Facebook/Instagram)',
    authorize_url: 'https://www.facebook.com/v19.0/dialog/oauth',
    token_url: 'https://graph.facebook.com/v19.0/oauth/access_token',
    pkce: false,
    default_scopes: ['public_profile'],
    extra_auth_params: {},
  },
  linkedin: {
    label: 'LinkedIn',
    authorize_url: 'https://www.linkedin.com/oauth/v2/authorization',
    token_url: 'https://www.linkedin.com/oauth/v2/accessToken',
    pkce: false,
    default_scopes: ['r_liteprofile'],
    extra_auth_params: {},
  },
  tiktok: {
    label: 'TikTok',
    authorize_url: 'https://www.tiktok.com/v2/auth/authorize/',
    token_url: 'https://open.tiktokapis.com/v2/oauth/token/',
    pkce: true,
    default_scopes: ['user.info.basic'],
    extra_auth_params: {},
  },
  hubspot: {
    label: 'HubSpot',
    authorize_url: 'https://app.hubspot.com/oauth/authorize',
    token_url: 'https://api.hubapi.com/oauth/v1/token',
    pkce: false,
    default_scopes: ['oauth'],
    extra_auth_params: {},
  },
};

/**
 * Resolve a provider config, layering manifest-supplied overrides on top of the
 * built-in catalog. Either source may be absent: a fully-inline connection
 * manifest needs no catalog entry; a catalogued provider needs no inline URLs.
 *
 * @param {string} providerKey         e.g. 'google'
 * @param {object} [overrides]         connection.oauth block (authorize_url, token_url, scopes, pkce, extra_auth_params)
 * @returns {object|null}              normalized provider config, or null if unresolvable
 */
export function resolveProvider(providerKey, overrides = {}) {
  const base = providerKey && PROVIDERS[providerKey] ? PROVIDERS[providerKey] : null;
  const authorize_url = overrides.authorize_url || base?.authorize_url || null;
  const token_url = overrides.token_url || base?.token_url || null;
  if (!authorize_url || !token_url) return null;

  const scopes = Array.isArray(overrides.scopes) && overrides.scopes.length
    ? overrides.scopes.slice()
    : (base?.default_scopes || []).slice();

  const pkce = typeof overrides.pkce === 'boolean' ? overrides.pkce : Boolean(base?.pkce);

  const extra_auth_params = {
    ...(base?.extra_auth_params || {}),
    ...(overrides.extra_auth_params && typeof overrides.extra_auth_params === 'object'
      ? overrides.extra_auth_params
      : {}),
  };

  return {
    provider: providerKey || 'custom',
    label: base?.label || providerKey || 'Custom provider',
    authorize_url,
    token_url,
    scopes,
    pkce,
    extra_auth_params,
  };
}

export function listProviders() {
  return Object.entries(PROVIDERS).map(([key, p]) => ({ provider: key, label: p.label, pkce: p.pkce }));
}

export { PROVIDERS };
