import { OAuth2Client } from 'google-auth-library'
import jwt from 'jsonwebtoken'
import jwksClient from 'jwks-rsa'

const getGoogleClientIds = () => {
  const raw = process.env.GOOGLE_OAUTH_CLIENT_IDS || ''
  return raw.split(',').map((s) => s.trim()).filter(Boolean)
}

const googleClient = new OAuth2Client()

/**
 * Verify a Google ID token against Google's JWKS.
 * Throws on invalid; returns { sub, email, email_verified } on success.
 * Intentionally omits the user's name — call sign is set in-app.
 */
export const verifyGoogleIdToken = async (idToken) => {
  const audience = getGoogleClientIds()
  if (audience.length === 0) {
    throw Object.assign(new Error('GOOGLE_OAUTH_CLIENT_IDS not configured'), {
      code: 'OAUTH_MISCONFIGURED', statusCode: 500,
    })
  }
  try {
    const ticket = await googleClient.verifyIdToken({ idToken, audience })
    const payload = ticket.getPayload()
    if (!payload?.sub) {
      throw new Error('Google token missing sub')
    }
    return {
      sub: payload.sub,
      email: payload.email,
      email_verified: payload.email_verified === true,
    }
  } catch (err) {
    throw Object.assign(new Error(err.message || 'Invalid Google token'), {
      code: 'GOOGLE_TOKEN_INVALID', statusCode: 401,
    })
  }
}

const appleJwks = jwksClient({
  jwksUri: 'https://appleid.apple.com/auth/keys',
  cache: true,
  cacheMaxAge: 24 * 60 * 60 * 1000,
  rateLimit: true,
})

const getApplePublicKey = (kid) => new Promise((resolve, reject) => {
  appleJwks.getSigningKey(kid, (err, key) => {
    if (err) return reject(err)
    resolve(key.getPublicKey())
  })
})

/**
 * Verify an Apple ID token against Apple's JWKS.
 * Throws on invalid; returns { sub, email? } on success.
 * Note: Apple only includes `email` on first sign-in; persist it then.
 */
export const verifyAppleIdToken = async (idToken) => {
  const audience = process.env.APPLE_SERVICES_ID
  if (!audience) {
    throw Object.assign(new Error('APPLE_SERVICES_ID not configured'), {
      code: 'OAUTH_MISCONFIGURED', statusCode: 500,
    })
  }
  try {
    const decoded = jwt.decode(idToken, { complete: true })
    if (!decoded?.header?.kid) throw new Error('Apple token missing kid header')

    const publicKey = await getApplePublicKey(decoded.header.kid)
    const payload = jwt.verify(idToken, publicKey, {
      algorithms: ['RS256'],
      audience,
      issuer: 'https://appleid.apple.com',
    })
    if (!payload?.sub) throw new Error('Apple token missing sub')

    return {
      sub: payload.sub,
      email: payload.email,
      email_verified: payload.email_verified === true || payload.email_verified === 'true',
    }
  } catch (err) {
    throw Object.assign(new Error(err.message || 'Invalid Apple token'), {
      code: 'APPLE_TOKEN_INVALID', statusCode: 401,
    })
  }
}
