package com.oliver.kidio.backend.plugins import com.oliver.kidio.backend.* import com.oliver.kidio.backend.domain.repository.KidioRepository import com.oliver.kidio.backend.security.JwtService import io.ktor.http.HttpStatusCode import io.ktor.server.application.* import io.ktor.server.auth.authenticate import io.ktor.server.auth.jwt.JWTPrincipal import io.ktor.server.auth.principal import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import org.mindrot.jbcrypt.BCrypt import java.util.UUID fun Application.configureRouting(repository: KidioRepository, jwtService : JwtService) { routing { post("/api/v1/auth/register") { val registerRequest = call.receive() if (registerRequest.email.isBlank() || registerRequest.passwordPlain.isBlank()) { call.respond(HttpStatusCode.BadRequest, "Bitte füllen Sie alle Felder aus") return@post } if (registerRequest.parentPin.length != 4) { call.respond(HttpStatusCode.BadRequest, "Die Eltern-PIN muss genau 4 Ziffern lang sein") return@post } val existingUser = repository.findByEmail(registerRequest.email) if (existingUser != null) { call.respond(HttpStatusCode.Conflict, "Ein Benutzer mit dieser E-Mail-Adresse existiert bereits") return@post } // Backend generiert die eindeutige User-ID val userId = UUID.randomUUID().toString() val passwordHash = BCrypt.hashpw(registerRequest.passwordPlain, BCrypt.gensalt()) //datenbank insert hinzufügen repository.registerUser(User(userId, registerRequest.email, passwordHash, registerRequest.familyName, registerRequest.childAge, registerRequest.parentPin)) val token = jwtService.generateToken(userId) call.respond( HttpStatusCode.Created, mapOf( "token" to token, "userId" to userId, "message" to "Registrierung erfolgreich" ) ) } // Health-Check get("/api/v1/health") { call.respond(mapOf("status" to "OK", "message" to "Kidio Backend läuft!")) } post ("/api/v1/auth/login" ) { val loginRequest = call.receive() val token = jwtService.generateToken(userId = loginRequest.userId) call.respond(mapOf("token" to token)) } authenticate("auth-jwt") { // 1. Alle verfügbaren Aufgaben abrufen get("/api/v1/tasks") { val tasks = repository.getAllTasks() call.respond(tasks) } // 2. Antwort auf eine Aufgabe überprüfen post("/api/v1/tasks/verify") { val request = call.receive() val principal = call.principal() val userId = principal?.payload?.getClaim("userId")?.asString() if (userId == null){ call.respond(HttpStatusCode.Unauthorized, mapOf("error" to "Ungültiges oder abgelaufenes Token")) return@post } val taskInfo = repository.getTaskAnswerAndReward(request.taskId) if (taskInfo == null) { call.respond( TaskVerifyResponse( isCorrect = false, earnedMinutes = 0, message = "Aufgabe nicht gefunden!" ) ) return@post } val (correctAnswer, reward) = taskInfo val isCorrect = request.selectedAnswer.trim() == correctAnswer.trim() if (isCorrect) { val currentScreentime = repository.getScreentime(userId) val newSeconds = currentScreentime + (reward * 60) repository.updateScreentime(userId, newSeconds) call.respond( TaskVerifyResponse( isCorrect = true, earnedMinutes = reward, message = "Super gemacht! Du hast $reward Minuten gewonnen." ) ) } else { call.respond( TaskVerifyResponse( isCorrect = false, earnedMinutes = 0, message = "Schade, das war leider falsch. Versuche es nochmal!" ) ) } } // 3. Bildschirmzeit synchronisieren post("/api/v1/screentime/sync") { val request = call.receive() val currentSeconds = repository.getScreentime(request.userId) var newSeconds = currentSeconds - request.usedSecondsSinceLastSync if (newSeconds < 0) newSeconds = 0 repository.updateScreentime(request.userId, newSeconds) call.respond( SyncResponse( remainingSeconds = newSeconds, isBlocked = newSeconds <= 0 ) ) } } } }