package de.krisenvorrat.server.plugins

import de.krisenvorrat.server.model.ErrorResponse
import de.krisenvorrat.server.repository.InventoryRepository
import de.krisenvorrat.server.repository.MessageRepository
import de.krisenvorrat.server.repository.UserRepository
import de.krisenvorrat.server.routes.adminRoutes
import de.krisenvorrat.server.routes.authRoutes
import de.krisenvorrat.server.routes.inventoryRoutes
import de.krisenvorrat.server.routes.messageRoutes
import de.krisenvorrat.server.routes.userRoutes
import de.krisenvorrat.server.routes.webSocketRoutes
import de.krisenvorrat.server.security.JwtService
import de.krisenvorrat.server.websocket.WebSocketManager
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.http.content.*
import io.ktor.server.plugins.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import kotlin.time.Duration.Companion.seconds

private const val MAX_BODY_SIZE = 1 * 1024 * 1024L // 1 MB

internal fun Application.configureRouting(
    inventoryRepository: InventoryRepository = InventoryRepository(),
    userRepository: UserRepository = UserRepository(),
    messageRepository: MessageRepository = MessageRepository(),
    jwtService: JwtService = JwtService(environment.config),
    wsManager: WebSocketManager = WebSocketManager()
) {
    install(WebSockets) {
        pingPeriod = 15.seconds
        timeout = 30.seconds
    }

    routing {
        intercept(ApplicationCallPipeline.Plugins) {
            val contentLength = call.request.header(HttpHeaders.ContentLength)?.toLongOrNull()
            if (contentLength != null && contentLength > MAX_BODY_SIZE) {
                call.respond(
                    HttpStatusCode.PayloadTooLarge,
                    ErrorResponse(status = 413, message = "Request body too large (max 1 MB)")
                )
                finish()
            }
        }

        get("/api/health") {
            call.respondText("OK", ContentType.Text.Plain, HttpStatusCode.OK)
        }

        // Public auth endpoints
        authRoutes(userRepository, jwtService)

        // Protected endpoints
        authenticate("auth-jwt") {
            inventoryRoutes(inventoryRepository, wsManager)
            adminRoutes(userRepository, inventoryRepository)
            messageRoutes(messageRepository, userRepository, wsManager)
            userRoutes(userRepository)
        }

        // WebSocket – auth via query param ?token=
        webSocketRoutes(wsManager, jwtService, messageRepository)

        // Admin web UI (static)
        staticResources("/admin", "static/admin")
    }
}
