/**
 * Google OAuth id_token verification via JWKS.
 *
 * Fetches Google's public JWKS and verifies the id_token signature,
 * audience (must match one of our client IDs), and issuer.
 */

import { createRemoteJWKSet, jwtVerify } from 'jose';
import { config } from '../../../lib/config.js';
import type { OAuthVerifiedIdentity } from './types.js';

const GOOGLE_JWKS_URI = 'https://www.googleapis.com/oauth2/v3/certs';
const GOOGLE_ISSUERS = ['https://accounts.google.com', 'accounts.google.com'];

let _jwks: ReturnType<typeof createRemoteJWKSet> | null = null;

function getJwks() {
  if (!_jwks) {
    _jwks = createRemoteJWKSet(new URL(GOOGLE_JWKS_URI));
  }
  return _jwks;
}

/** @internal Override JWKS for testing — do not use in production code. */
export function _setJwks(jwks: ReturnType<typeof createRemoteJWKSet>): void {
  _jwks = jwks;
}

/** @internal Reset JWKS to default for testing — do not use in production code. */
export function _resetJwks(): void {
  _jwks = null;
}

function getAcceptedAudiences(): string[] {
  const auds: string[] = [];
  if (config.GOOGLE_CLIENT_ID_WEB) auds.push(config.GOOGLE_CLIENT_ID_WEB);
  if (config.GOOGLE_CLIENT_ID_IOS) auds.push(config.GOOGLE_CLIENT_ID_IOS);
  if (config.GOOGLE_CLIENT_ID_ANDROID) auds.push(config.GOOGLE_CLIENT_ID_ANDROID);
  return auds;
}

export async function verifyGoogleIdToken(idToken: string): Promise<OAuthVerifiedIdentity> {
  const audiences = getAcceptedAudiences();
  if (audiences.length === 0) {
    throw new Error('No Google client IDs configured');
  }

  const { payload } = await jwtVerify(idToken, getJwks(), {
    issuer: GOOGLE_ISSUERS,
    audience: audiences,
  });

  const email = payload.email as string | undefined;
  const sub = payload.sub;
  if (!email || !sub) {
    throw new Error('Google id_token missing email or sub');
  }

  return {
    provider: 'google',
    providerUserId: sub,
    email: email.toLowerCase(),
    emailVerified: (payload.email_verified as boolean) ?? false,
    displayName: (payload.name as string) ?? undefined,
  };
}
