import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'

/**
 * Auth deletion trigger — cascades account deletion server-side.
 *
 * Fires when a Firebase Auth user is deleted (via client deleteAccount() or
 * Admin SDK). The Admin SDK bypasses Firestore rules, so this function can
 * reach everything the client cannot.
 *
 * Steps (all best-effort after the auth account is already gone):
 *  1. If the user was in a couple:
 *     a. Clear the partner's coupleId.
 *     b. Send the partner an FCM push notification.
 *     c. Recursively delete the couple doc + all subcollections.
 *  2. Delete all Storage objects under users/{uid}/ (profile photo etc.).
 *  3. Recursively delete the user doc + all subcollections
 *     (entitlements, fcmTokens, notification_queue).
 */
export const onUserDelete = functions.auth.user().onDelete(async (user) => {
  const uid = user.uid
  const db = admin.firestore()

  // ── 1. Couple unpair ──────────────────────────────────────────────────────

  const userDocRef = db.collection('users').doc(uid)
  const userDoc = await userDocRef.get()
  const coupleId = userDoc.exists
    ? (userDoc.data()?.coupleId as string | undefined)
    : undefined

  if (coupleId) {
    const coupleRef = db.collection('couples').doc(coupleId)
    const coupleDoc = await coupleRef.get()

    if (coupleDoc.exists) {
      const userIds = (coupleDoc.data()?.userIds ?? []) as string[]
      const partnerId = userIds.find((id) => id !== uid)

      if (partnerId) {
        const partnerRef = db.collection('users').doc(partnerId)
        const partnerDoc = await partnerRef.get()

        // Only act if the partner is still recorded in this couple.
        if (partnerDoc.exists && partnerDoc.data()?.coupleId === coupleId) {
          // Clear partner's coupleId first so the onCoupleLeave trigger does
          // not fire a second time (it would find no partner left to notify).
          await partnerRef.update({ coupleId: null })

          // Send push notification to the partner.
          await notifyPartner(partnerId, partnerDoc, db).catch((err) => {
            console.warn(`[onUserDelete] FCM notification to partner ${partnerId} failed:`, err)
          })
        }
      }

      // Recursively delete the couple doc + all subcollections.
      await db.recursiveDelete(coupleRef)
    }
  }

  // ── 2. Storage cleanup ────────────────────────────────────────────────────

  try {
    await admin.storage().bucket().deleteFiles({ prefix: `users/${uid}/` })
  } catch (err) {
    console.warn(`[onUserDelete] Storage cleanup failed for ${uid}:`, err)
  }

  // ── 3. User doc + subcollections ──────────────────────────────────────────

  await db.recursiveDelete(userDocRef)

  console.log(`[onUserDelete] completed cleanup for user ${uid}`)
})

async function notifyPartner(
  partnerId: string,
  partnerDoc: admin.firestore.DocumentSnapshot,
  db: admin.firestore.Firestore
): Promise<void> {
  const messaging = admin.messaging()

  // Collect FCM tokens (legacy field + fcmTokens subcollection).
  const tokens: string[] = []
  const legacyToken = partnerDoc.data()?.fcmToken
  if (typeof legacyToken === 'string' && legacyToken.length > 0) {
    tokens.push(legacyToken)
  }
  const tokenSnap = await db.collection('users').doc(partnerId).collection('fcmTokens').get()
  tokenSnap.docs.forEach((doc) => {
    const t = doc.data()?.token
    if (typeof t === 'string' && t.length > 0 && !tokens.includes(t)) {
      tokens.push(t)
    }
  })

  if (tokens.length === 0) return

  // Write an in-app notification record.
  await db
    .collection('users')
    .doc(partnerId)
    .collection('notification_queue')
    .add({
      type: 'partner_deleted_account',
      title: 'Your partner deleted their account',
      body: 'You are no longer paired. Tap to create a new invite.',
      read: false,
      createdAt: admin.firestore.FieldValue.serverTimestamp(),
    })

  const sendResults = await Promise.allSettled(
    tokens.map((token) =>
      messaging.send({
        token,
        notification: {
          title: 'Your partner deleted their account',
          body: 'You are no longer paired. Tap to create a new invite.',
        },
        data: { type: 'partner_deleted_account' },
      })
    )
  )

  sendResults.forEach((result, i) => {
    if (result.status === 'rejected') {
      console.warn(`[onUserDelete] FCM send to token ${tokens[i]} failed:`, result.reason)
    }
  })
}
