package de.kif.backend.route.api

import de.kif.backend.authenticate
import de.kif.backend.repository.RoomRepository
import de.kif.backend.repository.ScheduleRepository
import de.kif.common.model.Permission
import de.kif.common.model.Schedule
import io.ktor.application.call
import io.ktor.http.HttpStatusCode
import io.ktor.request.receive
import io.ktor.routing.Route
import io.ktor.routing.get
import io.ktor.routing.post

data class ScheduleMove(val day: Int, val time: Int, val roomId: Long)

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

    post("/api/schedules") {
        try {
            authenticate(Permission.SCHEDULE) {
                val schedule = call.receive<Schedule>()

                val id = ScheduleRepository.create(schedule)

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

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

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

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

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

    post("/api/schedule/{id}/delete") {
        try {
            authenticate(Permission.SCHEDULE) {
                val id = call.parameters["id"]?.toLongOrNull()

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

    post("/api/schedule/{id}/move") {
        try {
            authenticate(Permission.SCHEDULE) {
                val id = call.parameters["id"]?.toLongOrNull()
                val scheduleMove = call.receive<ScheduleMove>()
                var schedule = id?.let { ScheduleRepository.get(it) }
                val room = RoomRepository.get(scheduleMove.roomId)

                if (schedule != null && room != null) {
                    schedule = schedule.copy(day = scheduleMove.day, time = scheduleMove.time, room = room)

                    ScheduleRepository.update(schedule)

                    call.success()
                } else {
                    call.error(HttpStatusCode.NotFound)
                }
            } onFailure {
                call.error(HttpStatusCode.Unauthorized)
            }
        } catch (_: Exception) {
            call.error(HttpStatusCode.InternalServerError)
        }
    }
}
