/*
 * This file is part of LibEuFin.
 * Copyright (C) 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.api

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.github.smiley4.ktoropenapi.*
import io.ktor.util.pipeline.*
import io.prometheus.metrics.core.metrics.*
import io.prometheus.metrics.model.registry.PrometheusRegistry
import io.prometheus.metrics.model.snapshots.Unit
import io.prometheus.metrics.instrumentation.jvm.JvmMetrics;
import io.prometheus.metrics.expositionformats.ExpositionFormats
import tech.libeufin.common.*
import tech.libeufin.common.db.*
import tech.libeufin.bank.*
import tech.libeufin.bank.db.*
import tech.libeufin.bank.auth.*
import java.time.Instant
import java.io.ByteArrayOutputStream

object Metrics {
    @Volatile
    private var tanChannelCounter = Counter.builder()
                                        .name("libeufin_bank_tan_channel")
                                        .help("TAN script calls")
                                        .labelNames("channel", "exit")

    init {
        // Register JVM metrics 
        JvmMetrics.builder().register()
    }

    // TODO add database table counter info ?
}

fun Routing.observabilityApi(db: Database, cfg: BankConfig) {
    get("/taler-observability/config", {
        operationId = "getObservabilityConfig"
        description = "Get observability configuration"
        tags = listOf("Observability")
        response {
            code(HttpStatusCode.OK) { description = "Observability configuration"; body<TalerObservabilityConfig>() }
        }
    }) {
        call.respond(TalerObservabilityConfig())
    }
    authAdmin(db, cfg.pwCrypto, TokenLogicalScope.observability, cfg.basicAuthCompat) {
        get("/taler-observability/metrics", {
            operationId = "getMetrics"
            description = "Get Prometheus metrics"
            tags = listOf("Observability")
            protected = true
            securitySchemeNames("bearerAuth", "basicAuth")
            response {
                code(HttpStatusCode.OK) { description = "Prometheus metrics in text format" }
            }
        }) {
            val snapshot = PrometheusRegistry.defaultRegistry.scrape()
            val outputStream = ByteArrayOutputStream()
            ExpositionFormats.init().getPrometheusTextFormatWriter().write(outputStream, snapshot)
            call.respondText(outputStream.toString(Charsets.UTF_8), ContentType.parse("text/plain; version=0.0.4; charset=utf-8"))
        }
    }
}