package de.krisenvorrat.server

import de.krisenvorrat.server.db.DatabaseFactory
import de.krisenvorrat.server.model.VersionInfo
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.server.config.*
import io.ktor.server.testing.*
import kotlinx.serialization.json.Json
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test

class VersionEndpointTest {

    private val json = Json { ignoreUnknownKeys = true }

    private fun testApp(
        extraConfig: List<Pair<String, String>> = emptyList(),
        block: suspend ApplicationTestBuilder.() -> Unit
    ) = testApplication {
        environment {
            config = MapApplicationConfig(*(testMapConfig() + extraConfig).toTypedArray())
        }
        application {
            DatabaseFactory.init(
                jdbcUrl = "jdbc:h2:mem:test_${System.nanoTime()};DB_CLOSE_DELAY=-1",
                driver = "org.h2.Driver",
                adminPassword = "test-admin-pw"
            )
            configurePlugins()
        }
        block()
    }

    @Test
    fun test_versionEndpoint_returnsVersionInfo() = testApp {
        // When
        val response = client.get("/api/version")

        // Then
        assertEquals(HttpStatusCode.OK, response.status)
        val versionInfo = json.decodeFromString<VersionInfo>(response.bodyAsText())
        assertEquals(42, versionInfo.versionCode)
        assertEquals("2.1.0", versionInfo.versionName)
        assertTrue(versionInfo.apkUrl.endsWith("/static/app-latest.apk"))
    }

    @Test
    fun test_versionEndpoint_noAuthRequired() = testApp {
        // When – no bearer token
        val response = client.get("/api/version")

        // Then
        assertEquals(HttpStatusCode.OK, response.status)
    }

    @Test
    fun test_versionEndpoint_returnsJsonContentType() = testApp {
        // When
        val response = client.get("/api/version")

        // Then
        assertEquals(
            ContentType.Application.Json.withCharset(Charsets.UTF_8),
            response.contentType()
        )
    }

    @Test
    fun test_versionEndpoint_customConfig() = testApp(
        extraConfig = listOf(
            "krisenvorrat.appVersionCode" to "99",
            "krisenvorrat.appVersionName" to "3.0.0-beta"
        )
    ) {
        // When
        val response = client.get("/api/version")

        // Then
        val versionInfo = json.decodeFromString<VersionInfo>(response.bodyAsText())
        assertEquals(99, versionInfo.versionCode)
        assertEquals("3.0.0-beta", versionInfo.versionName)
    }

    @Test
    fun test_homepage_returnsHtml() = testApp {
        // When
        val response = client.get("/")

        // Then
        assertEquals(HttpStatusCode.OK, response.status)
        assertEquals(ContentType.Text.Html.withCharset(Charsets.UTF_8), response.contentType())
    }

    @Test
    fun test_homepage_containsAppName() = testApp {
        // When
        val body = client.get("/").bodyAsText()

        // Then
        assertTrue(body.contains("Krisenvorrat"))
    }

    @Test
    fun test_homepage_containsVersionInfo() = testApp {
        // When
        val body = client.get("/").bodyAsText()

        // Then
        assertTrue(body.contains("2.1.0"))
        assertTrue(body.contains("42"))
    }

    @Test
    fun test_homepage_containsQrCodeScript() = testApp {
        // When
        val body = client.get("/").bodyAsText()

        // Then
        assertTrue(body.contains("qrcode"))
        assertTrue(body.contains("QRCode"))
    }

    @Test
    fun test_homepage_containsApkDownloadLink() = testApp {
        // When
        val body = client.get("/").bodyAsText()

        // Then
        assertTrue(body.contains("/static/app-latest.apk"))
    }

    @Test
    fun test_homepage_noAuthRequired() = testApp {
        // When – no bearer token
        val response = client.get("/")

        // Then
        assertEquals(HttpStatusCode.OK, response.status)
    }

    @Test
    fun test_adminRoute_stillAccessible() = testApp {
        // When
        val response = client.get("/admin")

        // Then – staticResources returns 200 for the admin folder (or redirect)
        // The important thing is it doesn't return 404
        assertTrue(response.status != HttpStatusCode.NotFound)
    }

    @Test
    fun test_staticApk_returns404WhenNoFile() = testApp {
        // When – no APK file exists in data/
        val response = client.get("/static/app-latest.apk")

        // Then
        assertEquals(HttpStatusCode.NotFound, response.status)
    }
}
