package com.pixelized.shared.lwa.usecase

import kotlin.math.max
import kotlin.math.min
import kotlin.math.round
import kotlin.math.roundToInt

class SkillStepUseCase {

    data class SkillStep(
        val criticalSuccess: IntRange,
        val specialSuccess: IntRange,
        val success: IntRange,
        val failure: IntRange,
        val criticalFailure: IntRange,
    )

    /**
     * Helper method to compute the range in which a roll is a either critical, special, success or failure.
     */
    fun computeSkillStep(skill: Int): SkillStep {
        val criticalSuccess = 1..min(roundToInt { skill * 0.05f }, 99)
        val specialSuccess =
            (roundToInt { skill * 0.05f } + 1)..min(roundToInt { skill * 0.2f }, 99)
        val success = (roundToInt { skill * 0.2f } + 1)..min(skill, 99)
        val criticalFailure = 100 - max(4 - criticalSuccess.last, 0)..100
        val failure = (success.last + 1) until criticalFailure.first

        return SkillStep(
            criticalSuccess = criticalSuccess.takeIf { it.first <= it.last } ?: NONE,
            specialSuccess = specialSuccess.takeIf { it.first <= it.last } ?: NONE,
            success = success.takeIf { it.first <= it.last } ?: NONE,
            failure = failure.takeIf { it.first <= it.last } ?: NONE,
            criticalFailure = criticalFailure.takeIf { it.first <= it.last } ?: NONE,
        )
    }

    private inline fun roundToInt(block: () -> Float): Int = round(block()).roundToInt()

    fun exportWiki() {
        fun print(range: IntRange): String = when {
            range == NONE -> "-"
            range.first == range.last -> "${range.first}"
            else -> "${range.first} - ${range.last}"
        }
        repeat(100) { skill ->
            val step = computeSkillStep(skill + 1)
            println(
                "|!${skill + 1} " +
                        "|${print(step.criticalSuccess)} " +
                        "|${print(step.specialSuccess)} " +
                        "|${print(step.success)} " +
                        "|${print(step.failure)} " +
                        "|${print(step.criticalFailure)} " +
                        "|"
            )
        }
    }

    fun exportTest() {
        println("val expected = hashMapOf(")
        (1..500).forEach {
            println("    $it to ${computeSkillStep(it)},")
        }
        println(")")
    }

    companion object {
        private val NONE: IntRange = -1..-1
    }
}