import * as functions from 'firebase-functions'
import { GoogleAuth } from 'google-auth-library'

const PACKAGE_NAME = 'app.closer'
const PLAY_INTEGRITY_URL =
  `https://playintegrity.googleapis.com/v1/${PACKAGE_NAME}:decodeIntegrityToken`

/**
 * Verifies a Play Integrity API token server-side and returns whether the
 * device meets basic integrity requirements.
 *
 * Called by [PlayIntegrityChecker] on app startup. Requires the caller to be
 * authenticated — the Firebase Auth token is verified automatically by the
 * Functions runtime.
 *
 * Setup required before this function works in production:
 * 1. Enable the Play Integrity API in your Google Cloud project.
 * 2. Link the Cloud project to your Play Console app (Play Console →
 *    Setup → API access → Link to Cloud project).
 * 3. Grant the Cloud Functions service account the "Play Integrity API User"
 *    role in IAM, or use a dedicated service account key via
 *    GOOGLE_APPLICATION_CREDENTIALS.
 *
 * If the Play Integrity API is not configured the function fails-closed
 * (returns passed: false). Configure the API and grant the service account
 * the "Play Integrity API User" IAM role before deploying to production.
 */
export const checkDeviceIntegrity = functions.https.onCall(
  async (data: { token?: string }, context) => {
    if (!context.auth) {
      throw new functions.https.HttpsError(
        'unauthenticated',
        'Caller must be authenticated.'
      )
    }
    if (!context.app) {
      throw new functions.https.HttpsError(
        'failed-precondition',
        'App Check verification required.'
      )
    }

    const token = data?.token
    if (!token || typeof token !== 'string') {
      throw new functions.https.HttpsError(
        'invalid-argument',
        'token is required.'
      )
    }

    try {
      const verdicts = await decodeIntegrityToken(token)
      const passed =
        verdicts.includes('MEETS_DEVICE_INTEGRITY') ||
        verdicts.includes('MEETS_STRONG_INTEGRITY')
      return { passed, verdicts }
    } catch (err) {
      console.error('[checkDeviceIntegrity] verification failed:', err)
      // Fail-closed: an unverifiable request is treated as failed, not passed.
      // Ensure the Play Integrity API is enabled and the service account has
      // "Play Integrity API User" role before deploying to production.
      return { passed: false, verdicts: [], error: 'verification_unavailable' }
    }
  }
)

interface IntegrityResponse {
  tokenPayloadExternal?: {
    deviceIntegrity?: {
      deviceRecognitionVerdict?: string[]
    }
  }
}

async function decodeIntegrityToken(token: string): Promise<string[]> {
  const auth = new GoogleAuth({
    scopes: ['https://www.googleapis.com/auth/playintegrity'],
  })
  const client = await auth.getClient()
  const response = await client.request<IntegrityResponse>({
    url: PLAY_INTEGRITY_URL,
    method: 'POST',
    data: { integrity_token: token },
  })
  return (
    response.data.tokenPayloadExternal?.deviceIntegrity
      ?.deviceRecognitionVerdict ?? []
  )
}
