package dev.ulfrx.recipe

import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import io.ktor.server.application.Application
import org.flywaydb.core.Flyway
import org.slf4j.LoggerFactory
import org.jetbrains.exposed.sql.Database as ExposedDatabase

object Database {
    private val log = LoggerFactory.getLogger(Database::class.java)

    fun migrate(app: Application) {
        val (url, user, password) = readConfig(app)
        log.info("Connecting to {} as {} and running Flyway migrations", url, user)
        runCatching {
            Flyway
                .configure()
                .dataSource(url, user, password)
                .locations("classpath:db/migration")
                .baselineOnMigrate(true)
                .validateOnMigrate(true)
                .cleanDisabled(true)
                .load()
                .migrate()
        }.onFailure { ex ->
            log.error("Flyway migration failed — cannot start server", ex)
            throw IllegalStateException("Database unreachable or migration failed", ex)
        }
    }

    /**
     * Wire Exposed to a Hikari pool against the same JDBC URL Flyway used.
     * Must be called AFTER [migrate] so the schema is in place before the first
     * Exposed transaction runs (Phase 2 D-26).
     */
    fun connect(app: Application) {
        val (url, user, password) = readConfig(app)
        val ds =
            HikariDataSource(
                HikariConfig().apply {
                    jdbcUrl = url
                    username = user
                    setPassword(password)
                    maximumPoolSize = 10
                    minimumIdle = 2
                    poolName = "recipe-pool"
                },
            )
        ExposedDatabase.connect(ds)
        log.info("Exposed connected via Hikari pool '{}'", ds.poolName)
    }

    private data class Conf(
        val url: String,
        val user: String,
        val password: String,
    )

    private fun readConfig(app: Application): Conf =
        Conf(
            url =
                app.environment.config
                    .property("database.url")
                    .getString(),
            user =
                app.environment.config
                    .property("database.user")
                    .getString(),
            password =
                app.environment.config
                    .property("database.password")
                    .getString(),
        )
}
