package de.krisenvorrat.server.routes

import de.krisenvorrat.server.model.ErrorResponse
import de.krisenvorrat.server.repository.MessageRepository
import de.krisenvorrat.server.repository.UserRepository
import de.krisenvorrat.server.security.UserPrincipal
import de.krisenvorrat.server.websocket.WebSocketManager
import io.ktor.http.*
import io.ktor.server.auth.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Serializable
import java.util.UUID

@Serializable
internal data class SendMessageRequest(
    val id: String? = null,
    val receiverId: String,
    val body: String,
    val sentAt: Long
)

internal fun Route.messageRoutes(
    messageRepository: MessageRepository,
    userRepository: UserRepository,
    wsManager: WebSocketManager
) {
    route("/api/messages") {
        post {
            val principal = call.principal<UserPrincipal>()
                ?: return@post call.respond(
                    HttpStatusCode.Unauthorized,
                    ErrorResponse(status = 401, message = "Unauthorized")
                )
            val request = call.receive<SendMessageRequest>()
            if (request.body.isBlank()) {
                call.respond(
                    HttpStatusCode.BadRequest,
                    ErrorResponse(status = 400, message = "Body must not be empty")
                )
                return@post
            }
            if (userRepository.findById(request.receiverId) == null) {
                call.respond(
                    HttpStatusCode.NotFound,
                    ErrorResponse(status = 404, message = "Receiver not found")
                )
                return@post
            }
            val msgId = request.id ?: UUID.randomUUID().toString()
            val message = messageRepository.save(
                id = msgId,
                senderId = principal.userId,
                senderUsername = principal.username,
                receiverId = request.receiverId,
                body = request.body,
                sentAt = request.sentAt
            )
            wsManager.notifyNewMessage(request.receiverId, message)
            if (wsManager.isOnline(request.receiverId)) {
                messageRepository.markDelivered(msgId)
            }
            call.respond(HttpStatusCode.Created, message)
        }

        get("/{userId}") {
            val myId = call.principal<UserPrincipal>()?.userId
                ?: return@get call.respond(
                    HttpStatusCode.Unauthorized,
                    ErrorResponse(status = 401, message = "Unauthorized")
                )
            val otherId = call.parameters["userId"]
                ?: return@get call.respond(
                    HttpStatusCode.BadRequest,
                    ErrorResponse(status = 400, message = "Missing userId")
                )
            val messages = messageRepository.getConversation(myId, otherId)
            call.respond(HttpStatusCode.OK, messages)
        }
    }
}
