package app.closer.data.repository

import app.closer.data.local.CategoryDao
import app.closer.data.local.QuestionDao
import app.closer.data.local.mapper.toQuestion
import app.closer.data.local.mapper.toQuestionCategory
import app.closer.domain.model.Question
import app.closer.domain.model.QuestionCategory
import app.closer.domain.repository.QuestionRepository
import java.time.LocalDate
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class RoomQuestionRepository @Inject constructor(
    private val questionDao: QuestionDao,
    private val categoryDao: CategoryDao
) : QuestionRepository {

    /**
     * Deterministic per-day index into a pool of [count] questions. Seeded by the local
     * calendar day so the chosen daily question is stable across reloads and identical on
     * both partners' devices (which share this question DB) — never RANDOM().
     */
    private fun dailyOffset(count: Int): Int =
        if (count <= 0) 0 else (LocalDate.now().toEpochDay() % count).toInt()

    override suspend fun getDailyQuestion(): Question? {
        val count = questionDao.countDailyQuestion()
        if (count == 0) return null
        return questionDao.getDailyQuestionAt(dailyOffset(count))?.toQuestion()
    }

    override suspend fun getDailyQuestionForMode(modeTag: String, isPremium: Boolean): Question? {
        return if (isPremium) {
            dailyByModeTag(modeTag) ?: dailyFromPack() ?: getDailyQuestion()
        } else {
            freeDailyByModeTag(modeTag) ?: freeDailyFromPack() ?: getDailyQuestion()
        }
    }

    private suspend fun dailyByModeTag(modeTag: String): Question? {
        val count = questionDao.countDailyQuestionByModeTag(modeTag)
        if (count == 0) return null
        return questionDao.getDailyQuestionByModeTagAt(modeTag, dailyOffset(count))?.toQuestion()
    }

    private suspend fun dailyFromPack(): Question? {
        val count = questionDao.countDailyQuestionFromPack()
        if (count == 0) return null
        return questionDao.getDailyQuestionFromPackAt(dailyOffset(count))?.toQuestion()
    }

    private suspend fun freeDailyByModeTag(modeTag: String): Question? {
        val count = questionDao.countFreeDailyQuestionByModeTag(modeTag)
        if (count == 0) return null
        return questionDao.getFreeDailyQuestionByModeTagAt(modeTag, dailyOffset(count))?.toQuestion()
    }

    private suspend fun freeDailyFromPack(): Question? {
        val count = questionDao.countFreeDailyQuestionFromPack()
        if (count == 0) return null
        return questionDao.getFreeDailyQuestionFromPackAt(dailyOffset(count))?.toQuestion()
    }

    override suspend fun getQuestionById(id: String): Question? {
        return questionDao.getQuestionById(id)?.toQuestion()
    }

    override suspend fun getQuestionsByCategory(categoryId: String): List<Question> {
        return questionDao.getQuestionsByCategory(categoryId).map { it.toQuestion() }
    }

    override suspend fun getCategories(): List<QuestionCategory> {
        return categoryDao.getAllCategories().map { it.toQuestionCategory() }
    }

    override suspend fun getCategoryById(id: String): QuestionCategory? {
        return categoryDao.getCategoryById(id)?.toQuestionCategory()
    }

    override suspend fun getQuestionCountByCategory(categoryId: String): Int {
        return questionDao.getQuestionCountByCategory(categoryId)
    }

    override suspend fun getQuestionsByType(type: String): List<Question> {
        return questionDao.getQuestionsByType(type).map { it.toQuestion() }
    }

    override suspend fun getQuestionsForPrediction(): List<Question> {
        return questionDao.getQuestionsForPrediction().map { it.toQuestion() }
    }

    override suspend fun getDesireSyncQuestions(sex: String): List<Question> {
        return questionDao.getDesireSyncQuestions(sex).map { it.toQuestion() }
    }
}
