package app.closer.core.billing

import app.closer.data.remote.FirestoreCollections
import app.closer.domain.repository.CoupleRepository
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Couple-shared premium: a premium feature unlocks if EITHER partner has an active subscription, so a
 * single subscription covers the couple. Combines the current user's [EntitlementChecker.isPremium]
 * with a live read of the partner's `users/{partnerId}/entitlements/premium` doc (same active/expiry
 * rule as [FirestoreEntitlementChecker]). Reactive: flips the moment either side subscribes/expires.
 *
 * Exposes [isPremium]/[hasPremium] with the SAME shape as [EntitlementChecker] so it's a drop-in for
 * any feature gate (resolves the partner internally), plus [coupleHasPremium] when the caller already
 * knows the partner id.
 */
@Singleton
class CouplePremiumChecker @Inject constructor(
    private val entitlementChecker: EntitlementChecker,
    private val firestore: FirebaseFirestore,
    private val coupleRepository: CoupleRepository
) {
    /** Couple-shared premium for the current user (resolves the partner internally). Drop-in for EntitlementChecker. */
    fun isPremium(): Flow<Boolean> = flow {
        val uid = FirebaseAuth.getInstance().currentUser?.uid
        val partnerId = uid?.let {
            runCatching { coupleRepository.getCoupleForUser(it)?.userIds?.firstOrNull { id -> id != it } }.getOrNull()
        }
        emitAll(coupleHasPremium(partnerId))
    }

    /** One-shot couple-shared premium check. Drop-in for EntitlementChecker.hasPremium. */
    suspend fun hasPremium(): Boolean = isPremium().first()

    fun coupleHasPremium(partnerId: String?): Flow<Boolean> =
        if (partnerId.isNullOrBlank()) entitlementChecker.isPremium()
        else combine(entitlementChecker.isPremium(), observePartnerPremium(partnerId)) { mine, theirs ->
            mine || theirs
        }.distinctUntilChanged()

    private fun observePartnerPremium(partnerId: String): Flow<Boolean> = callbackFlow {
        val ref = firestore.collection(FirestoreCollections.USERS).document(partnerId)
            .collection(FirestoreCollections.Users.ENTITLEMENTS)
            .document(FirestoreCollections.Users.ENTITLEMENT_PREMIUM_DOC)
        val listener = ref.addSnapshotListener { snap, err ->
            if (err != null || snap == null || !snap.exists()) { trySend(false); return@addSnapshotListener }
            val premium = snap.getBoolean("premium") ?: false
            val expiresAt = snap.getTimestamp("expiresAt")
            val active = premium && (expiresAt == null || expiresAt.seconds > System.currentTimeMillis() / 1000)
            trySend(active)
        }
        awaitClose { listener.remove() }
    }
}
