@@ -2,6 +2,7 @@ package de.tum.cit.aet.genai.controller
22
33import de.tum.cit.aet.genai.dto.*
44import de.tum.cit.aet.genai.service.GenAiService
5+ import de.tum.cit.aet.genai.service.ChatMessageService
56import jakarta.validation.Valid
67import org.slf4j.LoggerFactory
78import org.springframework.http.HttpStatus
@@ -16,7 +17,8 @@ import org.springframework.web.context.request.async.DeferredResult
1617@RequestMapping(" /api/genai" )
1718@CrossOrigin(origins = [" *" ])
1819class GenAiController (
19- private val genAiService : GenAiService
20+ private val genAiService : GenAiService ,
21+ private val chatMessageService : ChatMessageService
2022) {
2123
2224 private val logger = LoggerFactory .getLogger(GenAiController ::class .java)
@@ -145,7 +147,7 @@ class GenAiController(
145147
146148 val result = DeferredResult <ResponseEntity <Any >>(600000L ) // 10 minutes timeout
147149
148- genAiService.getSessionAsync(sessionId, userId) { response, error ->
150+ genAiService.getSessionAsync(userId) { response, error ->
149151 if (error != null ) {
150152 logger.error(" Error getting session: {}" , error.message, error)
151153 result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
@@ -376,7 +378,7 @@ class GenAiController(
376378 return result
377379 }
378380
379- // New chat endpoints that match frontend expectations
381+ // Chat session endpoints (simplified to match Python service pattern)
380382 @PostMapping(" /chat/sessions" )
381383 fun createChatSession (
382384 @Valid @RequestBody request : ChatSessionRequest ,
@@ -386,19 +388,41 @@ class GenAiController(
386388
387389 val result = DeferredResult <ResponseEntity <Any >>(600000L ) // 10 minutes timeout
388390
389- genAiService.createChatSessionAsync(request, userId) { response, error ->
390- if (error != null ) {
391- logger.error(" Error creating chat session: {}" , error.message, error)
392- result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
393- ErrorResponse (
394- error = " Chat session creation failed" ,
395- message = " Failed to create chat session: ${error.message} " ,
396- timestamp = LocalDateTime .now().format(dateFormatter)
391+ // Python service doesn't have sessions - it just loads documents per user
392+ // If documents are provided, load the first one for this user (for chat only, no content generation)
393+ if (request.documentIds.isNotEmpty()) {
394+ val primaryDocumentId = request.documentIds.first()
395+
396+ genAiService.loadDocumentForChatAsync(primaryDocumentId, userId) { success, error ->
397+ if (error != null || ! success) {
398+ logger.error(" Error loading document for chat: {}" , error?.message ? : " Unknown error" )
399+ result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
400+ ErrorResponse (
401+ error = " Failed to initialize chat" ,
402+ message = " Could not load document for chat: ${error?.message ? : " Unknown error" } " ,
403+ timestamp = LocalDateTime .now().format(dateFormatter)
404+ )
405+ ))
406+ } else {
407+ // Return session response with actual message history
408+ val messages = chatMessageService.getSessionMessages(userId) // sessionId = userId
409+ val response = mapOf (
410+ " sessionId" to userId,
411+ " messages" to messages,
412+ " documentsInContext" to request.documentIds
397413 )
398- ))
399- } else {
400- result.setResult(ResponseEntity .ok(response))
414+ result.setResult(ResponseEntity .ok(response))
415+ }
401416 }
417+ } else {
418+ // No documents provided, return session with existing message history
419+ val messages = chatMessageService.getSessionMessages(userId) // sessionId = userId
420+ val response = mapOf (
421+ " sessionId" to userId,
422+ " messages" to messages,
423+ " documentsInContext" to emptyList<String >()
424+ )
425+ result.setResult(ResponseEntity .ok(response))
402426 }
403427
404428 return result
@@ -413,19 +437,26 @@ class GenAiController(
413437
414438 val result = DeferredResult <ResponseEntity <Any >>(600000L ) // 10 minutes timeout
415439
416- genAiService.getChatSessionAsync(sessionId, userId) { response, error ->
417- if (error != null ) {
418- logger.error(" Error getting chat session: {}" , error.message, error)
419- result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
420- ErrorResponse (
421- error = " Chat session retrieval failed" ,
422- message = " Failed to get chat session: ${error.message} " ,
423- timestamp = LocalDateTime .now().format(dateFormatter)
424- )
425- ))
426- } else {
427- result.setResult(ResponseEntity .ok(response))
428- }
440+ try {
441+ // Get actual message history from database
442+ val messages = chatMessageService.getSessionMessages(sessionId)
443+
444+ val response = mapOf (
445+ " sessionId" to sessionId,
446+ " messages" to messages,
447+ " documentsInContext" to emptyList<String >() // Would need to extract from message context if needed
448+ )
449+
450+ result.setResult(ResponseEntity .ok(response))
451+ } catch (e: Exception ) {
452+ logger.error(" Error getting chat session: {}" , e.message, e)
453+ result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
454+ ErrorResponse (
455+ error = " Failed to get chat session" ,
456+ message = " Could not retrieve chat history: ${e.message} " ,
457+ timestamp = LocalDateTime .now().format(dateFormatter)
458+ )
459+ ))
429460 }
430461
431462 return result
@@ -441,24 +472,103 @@ class GenAiController(
441472
442473 val result = DeferredResult <ResponseEntity <Any >>(600000L ) // 10 minutes timeout
443474
444- genAiService.sendChatMessageAsync(sessionId, request, userId) { response, error ->
445- if (error != null ) {
446- logger.error(" Error sending chat message: {}" , error.message, error)
447- result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
448- ErrorResponse (
449- error = " Message sending failed" ,
450- message = " Failed to send message: ${error.message} " ,
451- timestamp = LocalDateTime .now().format(dateFormatter)
452- )
453- ))
454- } else {
455- result.setResult(ResponseEntity .ok(response))
475+ try {
476+ // Save user message to database first
477+ chatMessageService.saveUserMessage(
478+ sessionId = sessionId,
479+ userId = userId,
480+ content = request.message,
481+ documentIds = request.documentIds
482+ )
483+
484+ // Use the simple chat functionality - Python service uses user_id for context
485+ val chatRequest = ChatRequest (message = request.message, userId = userId)
486+
487+ genAiService.chatAsync(chatRequest) { chatResponse, error ->
488+ if (error != null ) {
489+ logger.error(" Error sending chat message: {}" , error.message, error)
490+ result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
491+ ErrorResponse (
492+ error = " Message sending failed" ,
493+ message = " Failed to send message: ${error.message} " ,
494+ timestamp = LocalDateTime .now().format(dateFormatter)
495+ )
496+ ))
497+ } else {
498+ try {
499+ // Save bot response to database
500+ val botMessage = chatMessageService.saveBotMessage(
501+ sessionId = sessionId,
502+ userId = userId,
503+ content = chatResponse!! .response
504+ )
505+
506+ // Transform to expected response format
507+ val messageResponse = mapOf (
508+ " id" to (botMessage.id ? : java.util.UUID .randomUUID().toString()),
509+ " content" to chatResponse.response,
510+ " sender" to " bot" ,
511+ " timestamp" to chatResponse.timestamp,
512+ " sources" to null ,
513+ " documentReferences" to null
514+ )
515+ result.setResult(ResponseEntity .ok(messageResponse))
516+ } catch (e: Exception ) {
517+ logger.error(" Error saving bot message: {}" , e.message, e)
518+ // Still return the response even if saving failed
519+ val messageResponse = mapOf (
520+ " id" to java.util.UUID .randomUUID().toString(),
521+ " content" to chatResponse!! .response,
522+ " sender" to " bot" ,
523+ " timestamp" to chatResponse.timestamp,
524+ " sources" to null ,
525+ " documentReferences" to null
526+ )
527+ result.setResult(ResponseEntity .ok(messageResponse))
528+ }
529+ }
456530 }
531+ } catch (e: Exception ) {
532+ logger.error(" Error saving user message: {}" , e.message, e)
533+ result.setResult(ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(
534+ ErrorResponse (
535+ error = " Message saving failed" ,
536+ message = " Failed to save user message: ${e.message} " ,
537+ timestamp = LocalDateTime .now().format(dateFormatter)
538+ )
539+ ))
457540 }
458541
459542 return result
460543 }
461544
545+ @DeleteMapping(" /chat/sessions/{sessionId}/messages" )
546+ fun clearChatHistory (
547+ @PathVariable sessionId : String ,
548+ @RequestHeader(" X-User-ID" ) userId : String
549+ ): ResponseEntity <Map <String , Any >> {
550+ logger.info(" DELETE /genai/chat/sessions/{}/messages for user: {}" , sessionId, userId)
551+
552+ return try {
553+ val deletedCount = chatMessageService.clearSessionMessages(sessionId)
554+
555+ ResponseEntity .ok(mapOf<String , Any >(
556+ " message" to " Chat history cleared successfully" ,
557+ " deletedMessages" to deletedCount,
558+ " sessionId" to sessionId,
559+ " timestamp" to LocalDateTime .now().format(dateFormatter)
560+ ))
561+ } catch (e: Exception ) {
562+ logger.error(" Error clearing chat history: {}" , e.message, e)
563+ ResponseEntity .status(HttpStatus .INTERNAL_SERVER_ERROR ).body(mapOf<String , Any >(
564+ " error" to " Failed to clear chat history" ,
565+ " message" to (e.message ? : " Unknown error" ),
566+ " timestamp" to LocalDateTime .now().format(dateFormatter)
567+ ))
568+ }
569+ }
570+
571+
462572 @GetMapping(" /health" )
463573 fun healthCheck (): ResponseEntity <Map <String , String >> {
464574 return ResponseEntity .ok(mapOf (
0 commit comments