/*
 * This file is part of LibEuFin.
 * Copyright (C) 2024-2025 Taler Systems S.A.

 * LibEuFin is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3, or
 * (at your option) any later version.

 * LibEuFin is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
 * Public License for more details.

 * You should have received a copy of the GNU Affero General Public
 * License along with LibEuFin; see the file COPYING.  If not, see
 * <http://www.gnu.org/licenses/>
 */

package tech.libeufin.bank.cli

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.Context
import com.github.ajalt.clikt.parameters.groups.provideDelegate
import tech.libeufin.bank.bankConfig
import tech.libeufin.bank.logger
import tech.libeufin.common.TalerCmd
import tech.libeufin.common.crypto.PwCrypto

class BenchPwh : TalerCmd("bench-pwh") {
    override fun help(context: Context) = "Benchmark password hashing algorithm and configuration"

    override fun run() = cliCmd(logger) {
        val pwCrypto = bankConfig(config).pwCrypto

        when (pwCrypto) {
            is PwCrypto.Bcrypt -> println("Benching bcrypt with cost=${pwCrypto.cost} for 10s")
        }

        val start = System.currentTimeMillis()
        val stop = start + 10000 // 10s
        var count = 0

        while (true) {
            val now = System.currentTimeMillis()
            if (now < stop) {
                val password = (0..10).map {
                    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#".random()
                }.joinToString("")
                pwCrypto.hashpw(password) 
                count ++
            } else {
                val elapsed = (now-start).toDouble()
                val perSec = count.toDouble() / (elapsed / 1000.0)
                val iterTime = elapsed / count.toDouble()
                println("hash password in ${String.format("%.0f", iterTime)}ms  ${String.format("%.2f", perSec)} H/s")
                break
            }
        }
    }
}