/**
 * Microsoft OAuth id_token verification via JWKS.
 *
 * Supports multi-tenant (common endpoint) or single-tenant via MICROSOFT_TENANT_ID.
 */

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

function getJwksUri(): string {
  const tenant = config.MICROSOFT_TENANT_ID || 'common';
  return `https://login.microsoftonline.com/${tenant}/discovery/v2.0/keys`;
}

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

function getJwks() {
  if (!_jwks) {
    _jwks = createRemoteJWKSet(new URL(getJwksUri()));
  }
  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;
}

export async function verifyMicrosoftIdToken(idToken: string): Promise<OAuthVerifiedIdentity> {
  const clientId = config.MICROSOFT_CLIENT_ID;
  if (!clientId) {
    throw new Error('MICROSOFT_CLIENT_ID is not configured');
  }

  const { payload } = await jwtVerify(idToken, getJwks(), {
    audience: clientId,
  });

  // Microsoft uses 'preferred_username' or 'email' for the email
  const email = (payload.email as string) || (payload.preferred_username as string);
  const sub = payload.sub || (payload.oid as string);
  if (!email || !sub) {
    throw new Error('Microsoft id_token missing email or sub');
  }

  return {
    provider: 'microsoft',
    providerUserId: sub as string,
    email: email.toLowerCase(),
    emailVerified: true, // Microsoft verifies email
    displayName: (payload.name as string) ?? undefined,
  };
}
