package com.nisemoe.nise.controller

import com.nisemoe.generated.tables.references.USERS
import jakarta.validation.Valid
import jakarta.validation.constraints.Min
import org.jooq.DSLContext
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import java.time.OffsetDateTime

@RestController
class BanlistController(
    private val dslContext: DSLContext
) {

    companion object {

        const val MAX_BANLIST_ENTRIES_PER_PAGE = 100

    }

    data class BanlistRequest(
        @field:Min(1)
        val page: Int,
    )

    data class BanlistResponse(
        val pagination: BanlistPagination,
        val users: List<BanlistEntry>
    )

    data class BanlistPagination(
        val currentPage: Int,
        val pageSize: Int,
        val totalResults: Int
    ) {

        val totalPages: Int
            get() = if (totalResults == 0) 1 else (totalResults + pageSize - 1) / pageSize

    }

    data class BanlistEntry(
        val userId: Long,
        val username: String,
        val secondsPlayed: Long?,
        val pp: Double?,
        val rank: Long?,
        val isBanned: Boolean?,
        val approximateBanTime: OffsetDateTime?,
        val lastUpdate: OffsetDateTime?
    )

    @PostMapping("banlist")
    fun banUser(@RequestBody @Valid request: BanlistRequest): ResponseEntity<BanlistResponse> {
        //
        val pagination = BanlistPagination(
            request.page,
            MAX_BANLIST_ENTRIES_PER_PAGE,
            dslContext.fetchCount(USERS, USERS.IS_BANNED.eq(true))
        )

        dslContext.select(
            USERS.USER_ID,
            USERS.USERNAME,
            USERS.SECONDS_PLAYED,
            USERS.IS_BANNED,
            USERS.PP_RAW,
            USERS.RANK,
            USERS.SYS_LAST_UPDATE,
            USERS.APPROX_BAN_DATE
        )
            .from(USERS)
            .where(USERS.IS_BANNED.eq(true))
            .orderBy(USERS.APPROX_BAN_DATE.desc())
            .limit(MAX_BANLIST_ENTRIES_PER_PAGE)
            .offset((request.page - 1) * MAX_BANLIST_ENTRIES_PER_PAGE)
            .fetch()
            .map {
                BanlistEntry(
                    it[USERS.USER_ID]!!,
                    it[USERS.USERNAME]!!,
                    it[USERS.SECONDS_PLAYED],
                    it[USERS.PP_RAW],
                    it[USERS.RANK],
                    it[USERS.IS_BANNED],
                    it[USERS.APPROX_BAN_DATE],
                    it[USERS.SYS_LAST_UPDATE]
                )
            }
            .let {
                return ResponseEntity.ok(BanlistResponse(pagination, it))
            }
    }

}