package de.kif.backend.route.api

import de.kif.backend.authenticate
import de.kif.backend.repository.PostRepository
import de.kif.backend.util.markdownToHtml
import de.kif.common.model.Permission
import de.kif.common.model.Post
import io.ktor.application.call
import io.ktor.html.respondHtml
import io.ktor.http.HttpStatusCode
import io.ktor.request.receive
import io.ktor.request.receiveText
import io.ktor.routing.Route
import io.ktor.routing.get
import io.ktor.routing.post
import kotlinx.html.unsafe

fun Route.postApi() {
    get("/api/posts") {
        try {
            val posts = PostRepository.all()
            call.success(posts)
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }

    post("/api/posts") {
        try {
            authenticate(Permission.POST) {
                val post = call.receive<Post>()

                val id = PostRepository.create(post)

                call.success(mapOf("id" to id))
            } onFailure {
                call.error(HttpStatusCode.Unauthorized)
            }
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }

    get("/api/post/{id}") {
        try {
            val id = call.parameters["id"]?.toLongOrNull()
            val post = id?.let { PostRepository.get(it) }

            if (post != null) {
                call.success(post)
            } else {
                call.error(HttpStatusCode.NotFound)
            }
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }

    post("/api/post/{id}") {
        try {
            authenticate(Permission.POST) {
                val id = call.parameters["id"]?.toLongOrNull()
                val post = call.receive<Post>().copy(id = id)

                if (post.id != null) {
                    PostRepository.update(post)
                    call.success()
                } else {
                    call.error(HttpStatusCode.NotFound)
                }
            } onFailure {
                call.error(HttpStatusCode.Unauthorized)
            }
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }
    post("/api/post/{id}/delete") {
        try {
            authenticate(Permission.POST) {
                val id = call.parameters["id"]?.toLongOrNull()

                if (id != null) {
                    PostRepository.delete(id)
                    call.success()
                } else {
                    call.error(HttpStatusCode.NotFound)
                }
            } onFailure {
                call.error(HttpStatusCode.Unauthorized)
            }
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }

    get("/api/p/{url}") {
        try {
            val id = call.parameters["url"]
            val post = id?.let { PostRepository.getByUrl(it) }

            if (post != null) {
                call.respondHtml(HttpStatusCode.OK) {
                    unsafe {
                        raw(markdownToHtml(post.content))
                    }
                }
            } else {
                call.error(HttpStatusCode.NotFound)
            }
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }

    post("/api/render") {
        try {
            authenticate(Permission.POST) {
                val data = call.receiveText()
                val html = markdownToHtml(data)
                call.success(html)
            } onFailure {
                call.error(HttpStatusCode.Unauthorized)
            }
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }
}
