package com.tomhempel.rbarometer.scoring

import android.content.Context
import com.tomhempel.rbarometer.data.AnswerRepository
import com.tomhempel.rbarometer.data.CompletedQuestionnaireRepository
import com.tomhempel.rbarometer.network.ClientScoringReview
import com.tomhempel.rbarometer.network.QuestionnaireCache
import com.tomhempel.rbarometer.network.ScoringProfileDefinition
import com.tomhempel.rbarometer.network.ScoringReviewProfile
import com.tomhempel.rbarometer.questionnaire.AnswerKeyUtils
import com.google.gson.JsonParser

object LocalScoringReviewBuilder {

    suspend fun build(
        context: Context,
        clientCodes: List<String>,
        profiles: List<ScoringProfileDefinition>,
    ): List<ClientScoringReview> {
        if (profiles.isEmpty() || clientCodes.isEmpty()) return emptyList()

        val activeProfiles = profiles.filter { it.isActive }
        if (activeProfiles.isEmpty()) return emptyList()

        val questionnaireIds = activeProfiles
            .flatMap { it.questionnaires.map { m -> m.questionnaireID } }
            .distinct()

        return clientCodes.map { clientCode ->
            val completions = CompletedQuestionnaireRepository.getAllForClient(clientCode)
                .filter { it.isDone }
            val completedIds = completions.map { it.questionnaireId }.toSet()

            val pointsByQuestionnaire = mutableMapOf<String, Int>()
            for (qnId in questionnaireIds) {
                if (!completedIds.contains(qnId)) continue
                val detailJson = QuestionnaireCache.loadQuestionnaireJson(context, qnId) ?: continue
                val root = runCatching { JsonParser.parseString(detailJson).asJsonObject }.getOrNull()
                    ?: continue
                val questions = root.getAsJsonArray("questions") ?: continue
                val answers = AnswerRepository.getAnswersForClientAndQuestionnaire(clientCode, qnId)
                    .associateBy(
                        { AnswerKeyUtils.lookupKey(qnId, it.questionId) },
                        { it.answerValue },
                    )
                pointsByQuestionnaire[qnId] = QuestionnaireScoreCalculator.compute(questions, answers)
            }

            val reviewProfiles = activeProfiles.mapNotNull { profile ->
                val result = ProfileScoringEngine.computeProfile(
                    profile,
                    pointsByQuestionnaire,
                    completedIds,
                ) ?: return@mapNotNull null
                ScoringReviewProfile(
                    profileID = result.profileID,
                    name = result.name,
                    weightedTotal = result.weightedTotal,
                    calculatedBand = result.calculatedBand,
                    greenMin = profile.greenMin,
                    greenMax = profile.greenMax,
                    yellowMin = profile.yellowMin,
                    yellowMax = profile.yellowMax,
                    redMin = profile.redMin,
                    coachBand = null,
                    pendingReview = true,
                )
            }

            ClientScoringReview(clientCode = clientCode, profiles = reviewProfiles)
        }
    }
}
