package com.nisemoe.nise.database

import com.nisemoe.generated.tables.references.BEATMAPS
import com.nisemoe.generated.tables.references.SCORES
import com.nisemoe.nise.osu.OsuApi
import org.jooq.DSLContext
import org.jooq.impl.DSL.avg
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service

@Service
class BeatmapService(
    private val dslContext: DSLContext,
    private val osuApi: OsuApi
) {

    private val logger = LoggerFactory.getLogger(javaClass)

    fun getBeatmapFile(beatmapId: Int): String? {
        // Fetch the beatmap file from database
        var beatmapFile = dslContext.select(BEATMAPS.BEATMAP_FILE)
            .from(BEATMAPS)
            .where(BEATMAPS.BEATMAP_ID.eq(beatmapId))
            .fetchOneInto(String::class.java)

        if(!beatmapFile.isNullOrBlank()) {
            return beatmapFile
        }

        this.logger.warn("Failed to fetch beatmap file for beatmap_id = $beatmapId from database")

        beatmapFile = this.osuApi.getBeatmapFile(beatmapId = beatmapId)

        if(beatmapFile == null) {
            this.logger.error("Failed to fetch beatmap file for beatmap_id = $beatmapId from osu!api")
            return null
        } else {
            dslContext.update(BEATMAPS)
                .set(BEATMAPS.BEATMAP_FILE, beatmapFile)
                .where(BEATMAPS.BEATMAP_ID.eq(beatmapId))
                .execute()
            return beatmapFile
        }
    }

    fun getAverageUR(beatmapId: Int, excludeReplayId: Long): Double? {
        val condition = SCORES.BEATMAP_ID.eq(beatmapId)
            .and(SCORES.UR.isNotNull)
            .and(SCORES.REPLAY_ID.notEqual(excludeReplayId))

        val totalScores = dslContext.fetchCount(
            SCORES, condition
        )

        if(totalScores < 50)
            return null

        return dslContext
            .select(avg(SCORES.UR))
            .from(SCORES)
            .where(condition)
            .fetchOneInto(Double::class.java)
    }

}