package {{ group_id }}.{{ project_name_snake }}

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction

@Serializable
data class ItemRequest(val name: String, val description: String? = null)

@Serializable
data class ItemResponse(val id: Int, val name: String, val description: String?)

fun Application.configureRouting() {
    routing {
        get("/health") {
            call.respond(mapOf("status" to "ok"))
        }

        route("/items") {
            get {
                val items = transaction {
                    Items.selectAll().map {
                        ItemResponse(it[Items.id], it[Items.name], it[Items.description])
                    }
                }
                call.respond(items)
            }

            get("/{id}") {
                val id = call.parameters["id"]?.toIntOrNull()
                    ?: return@get call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid ID"))
                val item = transaction {
                    Items.selectAll().where { Items.id eq id }.singleOrNull()?.let {
                        ItemResponse(it[Items.id], it[Items.name], it[Items.description])
                    }
                }
                if (item != null) call.respond(item)
                else call.respond(HttpStatusCode.NotFound, mapOf("error" to "Not found"))
            }

            post {
                val req = call.receive<ItemRequest>()
                val id = transaction {
                    Items.insert {
                        it[name] = req.name
                        it[description] = req.description
                    } get Items.id
                }
                call.respond(HttpStatusCode.Created, ItemResponse(id, req.name, req.description))
            }

            delete("/{id}") {
                val id = call.parameters["id"]?.toIntOrNull()
                    ?: return@delete call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid ID"))
                val deleted = transaction { Items.deleteWhere { Items.id eq id } }
                if (deleted > 0) call.respond(HttpStatusCode.NoContent)
                else call.respond(HttpStatusCode.NotFound, mapOf("error" to "Not found"))
            }
        }
    }
}
