package app.closer.data.remote

import app.closer.domain.model.TimeCapsule
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.tasks.await
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FirestoreCapsuleDataSource @Inject constructor(private val db: FirebaseFirestore) {

    private fun col(coupleId: String) =
        db.collection(FirestoreCollections.COUPLES)
            .document(coupleId)
            .collection(FirestoreCollections.Couples.CAPSULES)

    fun observeCapsules(coupleId: String): Flow<List<TimeCapsule>> = callbackFlow {
        val reg = col(coupleId)
            .orderBy("createdAt", com.google.firebase.firestore.Query.Direction.DESCENDING)
            .addSnapshotListener { snap, err ->
                if (err != null || snap == null) return@addSnapshotListener
                trySend(snap.documents.mapNotNull { doc ->
                    runCatching {
                        TimeCapsule(
                            id = doc.id,
                            coupleId = coupleId,
                            authorId = doc.getString("authorId") ?: "",
                            title = doc.getString("title") ?: "",
                            content = doc.getString("content") ?: "",
                            promptUsed = doc.getString("promptUsed"),
                            unlockAt = doc.getLong("unlockAt") ?: 0L,
                            createdAt = doc.getLong("createdAt") ?: 0L,
                            status = doc.getString("status") ?: "sealed"
                        )
                    }.getOrNull()
                })
            }
        awaitClose { reg.remove() }
    }

    suspend fun createCapsule(capsule: TimeCapsule): String {
        val ref = col(capsule.coupleId).document()
        ref.set(
            mapOf(
                "authorId" to capsule.authorId,
                "title" to capsule.title,
                "content" to capsule.content,
                "promptUsed" to capsule.promptUsed,
                "unlockAt" to capsule.unlockAt,
                "createdAt" to capsule.createdAt,
                "status" to "sealed"
            )
        ).await()
        return ref.id
    }

    suspend fun getCapsules(coupleId: String): List<TimeCapsule> =
        col(coupleId)
            .orderBy("createdAt", com.google.firebase.firestore.Query.Direction.DESCENDING)
            .get()
            .await()
            .documents
            .mapNotNull { doc ->
                runCatching {
                    TimeCapsule(
                        id = doc.id,
                        coupleId = coupleId,
                        authorId = doc.getString("authorId") ?: "",
                        title = doc.getString("title") ?: "",
                        content = doc.getString("content") ?: "",
                        promptUsed = doc.getString("promptUsed"),
                        unlockAt = doc.getLong("unlockAt") ?: 0L,
                        createdAt = doc.getLong("createdAt") ?: 0L,
                        status = doc.getString("status") ?: "sealed"
                    )
                }.getOrNull()
            }

    suspend fun unlockCapsule(coupleId: String, capsuleId: String) {
        col(coupleId).document(capsuleId).update("status", "unlocked").await()
    }
}
