package app.closer.data.repository

import app.closer.core.crash.CrashReporter
import app.closer.crypto.CoupleEncryptionManager
import app.closer.data.remote.FirestoreCoupleDataSource
import app.closer.data.remote.FirestoreUserDataSource
import app.closer.domain.model.Couple
import app.closer.domain.repository.CoupleRepository
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class CoupleRepositoryImpl @Inject constructor(
    private val coupleDataSource: FirestoreCoupleDataSource,
    private val userDataSource: FirestoreUserDataSource,
    private val encryptionManager: CoupleEncryptionManager,
    private val crashReporter: CrashReporter
) : CoupleRepository {

    override suspend fun getCoupleForUser(userId: String): Couple? {
        val coupleId = runCatching { userDataSource.getUser(userId)?.coupleId }
            .onFailure { crashReporter.recordException(it) }
            .getOrNull() ?: return null
        return runCatching { coupleDataSource.getCoupleById(coupleId) }
            .onFailure { crashReporter.recordException(it) }
            .getOrNull()
    }

    override suspend fun createCouple(
        inviterUserId: String,
        acceptorUserId: String,
        inviteCode: String,
        recoveryPhrase: String
    ): Result<String> = runCatching {
        // Acceptor flow now uses the acceptInviteCallable Cloud Function, which
        // atomically creates the couple, updates users, and marks the invite accepted.
        error("Direct couple creation from the client is no longer supported; use InviteRepository.acceptInvite.")
    }

    override suspend fun updateStreak(coupleId: String): Result<Unit> = runCatching {
        coupleDataSource.updateStreak(coupleId)
    }

    override suspend fun leaveCouple(userId: String): Result<Unit> = runCatching {
        val coupleId = userDataSource.getUser(userId)?.coupleId
        coupleDataSource.leaveCouple()
        if (coupleId != null) encryptionManager.deleteKeyset(coupleId)
    }

    override suspend fun changeRecoveryPhrase(coupleId: String, newPhrase: String): Result<Unit> = runCatching {
        val newWrapped = encryptionManager.rewrapWithNewPhrase(coupleId, newPhrase).getOrElse { throw it }
        coupleDataSource.updateWrappedKey(coupleId, newWrapped)
    }
}
