// OAuth 2.0 PKCE client — SuperOAuth consumer for TetaRdPG
// Adapted from OriginsDigital reference pattern

const OAUTH_URL       = import.meta.env.VITE_OAUTH_URL       || '';
const OAUTH_CLIENT_ID = import.meta.env.VITE_OAUTH_CLIENT_ID || '';

const SESSION_KEY_VERIFIER = 'trpg_pkce_verifier';

// --- PKCE helpers ---

function base64UrlEncode(buffer: ArrayBuffer): string {
  return btoa(String.fromCharCode(...new Uint8Array(buffer)))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');
}

export function generateCodeVerifier(): string {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return base64UrlEncode(array.buffer);
}

export async function generateCodeChallenge(verifier: string): Promise<string> {
  const data   = new TextEncoder().encode(verifier);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return base64UrlEncode(digest);
}

// --- Auth URL ---

export async function buildAuthUrl(
  redirectUri: string,
  provider: string,
  scope = 'openid profile email',
  clientId = OAUTH_CLIENT_ID,
): Promise<{ url: string; verifier: string }> {
  const verifier  = generateCodeVerifier();
  const challenge = await generateCodeChallenge(verifier);
  const state     = base64UrlEncode(crypto.getRandomValues(new Uint8Array(16)).buffer);

  const params = new URLSearchParams({
    response_type:         'code',
    client_id:             clientId,
    redirect_uri:          redirectUri,
    scope,
    state,
    provider,
    code_challenge:        challenge,
    code_challenge_method: 'S256',
  });

  return {
    url:      `${OAUTH_URL}/oauth/authorize?${params.toString()}`,
    verifier,
  };
}

// --- Token exchange ---

export interface TokenResponse {
  access_token: string;
  refresh_token?: string;
  token_type: string;
  expires_in: number;
  scope?: string;
}

export async function exchangeCode(
  code: string,
  verifier: string,
  redirectUri: string,
  clientId = OAUTH_CLIENT_ID,
): Promise<TokenResponse> {
  const response = await fetch(`${OAUTH_URL}/oauth/token`, {
    method:  'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type:    'authorization_code',
      client_id:     clientId,
      code,
      code_verifier: verifier,
      redirect_uri:  redirectUri,
    }).toString(),
  });

  if (!response.ok) {
    const text = await response.text().catch(() => '');
    throw new Error(`OAuth token exchange failed (${response.status}): ${text}`);
  }

  const data = await response.json() as TokenResponse;
  if (!data.access_token) throw new Error('No access_token in OAuth response');

  return data;
}

// --- PKCE verifier persistence (avant redirect) ---

export function saveVerifier(verifier: string): void {
  localStorage.setItem(SESSION_KEY_VERIFIER, verifier);
}

export function loadVerifier(): string | null {
  return localStorage.getItem(SESSION_KEY_VERIFIER);
}

export function clearVerifier(): void {
  localStorage.removeItem(SESSION_KEY_VERIFIER);
}
