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

/**
 * Firestore trigger that notifies the remaining partner when a user's coupleId
 * field is cleared (i.e. the user left the couple or was removed).
 *
 * Path: users/{userId}
 * Condition: previous coupleId was non-empty and new coupleId is null/missing.
 */
export const onCoupleLeave = functions.firestore
  .document('users/{userId}')
  .onUpdate(async (change, context) => {
    const { userId } = context.params as { userId: string }

    const previousData = change.before.data() ?? {}
    const currentData = change.after.data() ?? {}

    const previousCoupleId = previousData.coupleId
    const currentCoupleId = currentData.coupleId

    // Only act when coupleId transitions from a real value to null/empty.
    if (!previousCoupleId || typeof previousCoupleId !== 'string') {
      return
    }
    if (currentCoupleId) {
      return
    }

    const db = admin.firestore()
    const messaging = admin.messaging()

    const coupleDoc = await db.collection('couples').doc(previousCoupleId).get()
    if (!coupleDoc.exists) {
      console.warn(`[onCoupleLeave] couple ${previousCoupleId} not found`)
      return
    }

    const userIds = (coupleDoc.data()?.userIds ?? []) as string[]
    const partnerId = userIds.find((uid) => uid !== userId)
    if (!partnerId) {
      console.warn(`[onCoupleLeave] no partner found for couple ${previousCoupleId}`)
      return
    }

    // Make sure the partner is still paired in this couple.
    // If both users are leaving simultaneously, avoid duplicate/phantom notifications.
    const partnerUserDoc = await db.collection('users').doc(partnerId).get()
    const partnerCoupleId = partnerUserDoc.data()?.coupleId
    if (partnerCoupleId !== previousCoupleId) {
      console.log(
        `[onCoupleLeave] partner ${partnerId} is no longer in couple ${previousCoupleId}; skipping notification`
      )
      return
    }

    const notificationPayload = {
      type: 'partner_left',
      title: 'Your partner has left',
      body: 'You are no longer paired. Tap to create a new invite.',
    }

    // Write an in-app notification record for the partner.
    // This is read-only denied for clients; the Cloud Function writes it.
    await db
      .collection('users')
      .doc(partnerId)
      .collection('notification_queue')
      .add({
        ...notificationPayload,
        read: false,
        createdAt: admin.firestore.FieldValue.serverTimestamp(),
      })

    // Collect the partner's FCM tokens (legacy field + fcmTokens subcollection).
    const tokens: string[] = []
    if (partnerUserDoc.exists) {
      const legacyToken = partnerUserDoc.data()?.fcmToken
      if (typeof legacyToken === 'string' && legacyToken.length > 0) {
        tokens.push(legacyToken)
      }
    }

    const tokenSnapshot = await db
      .collection('users')
      .doc(partnerId)
      .collection('fcmTokens')
      .get()
    tokenSnapshot.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) {
      console.log(`[onCoupleLeave] no FCM tokens for partner ${partnerId}`)
      return
    }

    const fcmMessage: admin.messaging.Message = {
      token: tokens[0],
      notification: {
        title: notificationPayload.title,
        body: notificationPayload.body,
      },
      data: {
        type: notificationPayload.type,
      },
    }

    const sendResults = await Promise.allSettled(
      tokens.map((token) => messaging.send({ ...fcmMessage, token }))
    )

    const failures: string[] = []
    sendResults.forEach((result, index) => {
      if (result.status === 'rejected') {
        failures.push(`${tokens[index]}: ${String(result.reason)}`)
      }
    })

    if (failures.length > 0) {
      console.error(`[onCoupleLeave] some notifications failed:`, failures)
    }

    console.log(
      `[onCoupleLeave] notified partner ${partnerId} that user ${userId} left couple ${previousCoupleId}`
    )
  })
