package app.closer.domain.usecase

import app.closer.core.billing.EntitlementChecker
import app.closer.core.crash.CrashReporter
import app.closer.data.remote.FirestoreAnswerDataSource
import app.closer.domain.DailyModeResolver
import app.closer.domain.model.Question
import app.closer.domain.repository.AuthRepository
import app.closer.domain.repository.CoupleRepository
import app.closer.domain.repository.QuestionRepository
import kotlinx.coroutines.flow.first
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Single source of truth for "today's daily question" so the Home card and the daily-question
 * screen always resolve the SAME question. Previously Home used [QuestionRepository.getDailyQuestion]
 * (a different pool) while the screen used the Firestore assignment + mode pool — they showed
 * different questions, so Home's answered/waiting detection never matched what the user answered,
 * which made it re-ask after answering.
 *
 * Resolution order (paired): Firestore assignment → local question by that id → deterministic
 * mode-tagged daily question → deterministic generic daily question. Unpaired falls straight to
 * the deterministic local question for today's mode.
 */
@Singleton
class DailyQuestionResolver @Inject constructor(
    private val questionRepository: QuestionRepository,
    private val coupleRepository: CoupleRepository,
    private val authRepository: AuthRepository,
    private val firestoreAnswerDataSource: FirestoreAnswerDataSource,
    private val entitlementChecker: EntitlementChecker,
    private val crashReporter: CrashReporter,
) {
    data class Resolved(
        val coupleId: String?,
        val question: Question?,
        val date: String,
        val mode: DailyModeResolver.DailyMode,
    )

    suspend fun resolve(): Resolved {
        val mode = DailyModeResolver.resolve()
        val today = FirestoreAnswerDataSource.todayLocalDateString()
        val isPremium = runCatching { entitlementChecker.isPremium().first() }.getOrDefault(false)

        val couple = authRepository.currentUserId?.let { uid ->
            runCatching { coupleRepository.getCoupleForUser(uid) }
                .onFailure { crashReporter.recordException(it) }
                .getOrNull()
        }

        if (couple == null) {
            val q = questionRepository.getDailyQuestionForMode(mode.modeTag, isPremium)
                ?: questionRepository.getDailyQuestion()
            return Resolved(coupleId = null, question = q, date = today, mode = mode)
        }

        val coupleId = couple.id
        val assignment = runCatching {
            firestoreAnswerDataSource.getDailyQuestionAssignment(coupleId, today)
        }.onFailure { crashReporter.recordException(it) }.getOrNull()

        val question = if (assignment != null) {
            questionRepository.getQuestionById(assignment.questionId)
                ?: questionRepository.getDailyQuestionForMode(mode.modeTag, isPremium)
                ?: questionRepository.getDailyQuestion()
        } else {
            // No assignment yet — request one, but stay usable with the deterministic local
            // question (identical on both devices) if the call fails.
            runCatching {
                firestoreAnswerDataSource.requestDailyQuestionAssignment(coupleId, today)
                questionRepository.getQuestionById(
                    firestoreAnswerDataSource.getDailyQuestionAssignment(coupleId, today)?.questionId ?: ""
                )
            }.onFailure { crashReporter.recordException(it) }.getOrNull()
                ?: questionRepository.getDailyQuestionForMode(mode.modeTag, isPremium)
                ?: questionRepository.getDailyQuestion()
        }

        return Resolved(coupleId = coupleId, question = question, date = today, mode = mode)
    }
}
