package app.closer.data.repository

import app.closer.data.remote.FirestoreDateMatchDataSource
import app.closer.data.remote.FirestoreDateSwipeDataSource
import app.closer.domain.model.DateIdea
import app.closer.domain.model.DateMatch
import app.closer.domain.model.DateSwipe
import app.closer.domain.model.SwipeAction
import app.closer.domain.repository.DateMatchRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Implementation of [DateMatchRepository].
 *
 * Date ideas are currently loaded from an in-memory seed catalog that is also
 * shipped as a Cloud Function seed. Firestore is the source of truth for
 * per-partner swipes and revealed matches.
 *
 * Mutual match detection is performed server-side by the
 * `createDateMatchOnMutualLove` Cloud Function: the `date_matches` collection is
 * server-write-only (Firestore rules deny client writes), so when both partners
 * swipe [SwipeAction.LOVE] on an idea the function creates the match and it
 * arrives on the client via [observeMatches]. [recordSwipe] therefore only
 * records the swipe and always resolves with a null match.
 */
@Singleton
class DateMatchRepositoryImpl @Inject constructor(
    private val swipeDataSource: FirestoreDateSwipeDataSource,
    private val matchDataSource: FirestoreDateMatchDataSource
) : DateMatchRepository {

    override suspend fun getDateIdeas(): List<DateIdea> = DateIdeaSeed.all

    override suspend fun recordSwipe(
        coupleId: String,
        userId: String,
        dateIdeaId: String,
        action: SwipeAction
    ): Result<DateMatch?> = runCatching {
        val swipe = DateSwipe(
            dateIdeaId = dateIdeaId,
            userId = userId,
            action = action,
            swipedAt = System.currentTimeMillis()
        )
        swipeDataSource.recordSwipe(coupleId, swipe)
        // Match creation is server-side (see class docs); surfaced via observeMatches.
        null
    }

    override suspend fun getOwnSwipe(coupleId: String, userId: String, dateIdeaId: String): DateSwipe? {
        return swipeDataSource.getSwipe(coupleId, dateIdeaId, userId)
    }

    override fun observeOwnSwipes(coupleId: String, userId: String): Flow<List<DateSwipe>> {
        return swipeDataSource.observeOwnSwipes(coupleId, userId)
    }

    override fun observeMatches(coupleId: String): Flow<List<DateMatch>> {
        return matchDataSource.observeMatches(coupleId)
    }

    override suspend fun getPartnerSwipes(coupleId: String, partnerId: String): List<DateSwipe> {
        return swipeDataSource.observeOwnSwipes(coupleId, partnerId, once = true).first()
    }
}