NotesController.java

package com.medilabo.solutions.front.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.medilabo.solutions.front.client.GatewayServiceClient;
import com.medilabo.solutions.front.dto.PatientDto;
import com.medilabo.solutions.front.dto.NoteDto;

import jakarta.validation.Valid;
import java.util.List;

@Controller
public class NotesController {

    private static final Logger logger = LoggerFactory.getLogger(NotesController.class);

    @Autowired
    private GatewayServiceClient gatewayServiceClient;

    /**
     * Retrieves and displays patient notes along with patient information and risk
     * assessment.
     * 
     * This method fetches comprehensive patient data including:
     * - Patient details by ID
     * - All notes associated with the patient
     * - Risk assessment level for the patient
     * 
     * It also prepares a new empty note object for potential note creation.
     * In case of any error during data retrieval, an error message is added to the
     * model.
     * 
     * @param patientId the unique identifier of the patient whose notes are to be
     *                  retrieved
     * @param model     the Spring MVC model to which attributes are added for view
     *                  rendering
     * @return the name of the view template ("notes") to be rendered
     * 
     * @throws Exception if there's an error during patient data retrieval from
     *                   gateway services
     */
    @GetMapping("/notes/{id}")
    public String getPatientNotes(@PathVariable("id") Long patientId, Model model) {
        try {
            PatientDto patient = gatewayServiceClient.getPatientById(patientId);
            model.addAttribute("patient", patient);

            List<NoteDto> notes = gatewayServiceClient.getNoteByPatientId(patientId.intValue());
            model.addAttribute("notes", notes);

            String riskAssessment = gatewayServiceClient.getAssessmentById(patientId);
            model.addAttribute("riskLevel", riskAssessment);

            NoteDto newNote = new NoteDto();
            newNote.setPatId(patientId.intValue());
            model.addAttribute("newNote", newNote);

            logger.info("Successfully retrieved patient {} with {} notes", patientId, notes.size());

        } catch (Exception e) {
            logger.error("Error retrieving patient notes for ID {}: {}", patientId, e.getMessage());
            model.addAttribute("error", "Erreur lors de la récupération des données du patient");
        }

        return "notes";
    }

    /**
     * Adds a new note for a specific patient.
     * 
     * This method handles the POST request to create a new note associated with a
     * patient.
     * It validates the note data, retrieves patient information to set the patient
     * name,
     * and saves the note through the gateway service client.
     * 
     * @param patientId          the unique identifier of the patient for whom the
     *                           note is being added
     * @param noteDto            the note data transfer object containing the note
     *                           information to be saved
     * @param bindingResult      the result of the validation process for the
     *                           noteDto
     * @param redirectAttributes attributes to be passed to the redirect view for
     *                           displaying messages
     * @return a redirect URL to the notes page for the specified patient
     * 
     * @throws Exception if there's an error during patient retrieval or note
     *                   creation
     * 
     *                   The method performs the following operations:
     *                   - Validates the input note data and returns with error
     *                   message if validation fails
     *                   - Retrieves patient information to set the patient name in
     *                   the note
     *                   - Sets the patient ID and clears any existing note ID for
     *                   auto-generation
     *                   - Creates the note through the gateway service
     *                   - Adds success or error messages to redirect attributes
     *                   - Logs the operation result for monitoring purposes
     */
    @PostMapping("/notes/{id}")
    public String addNote(@PathVariable("id") Long patientId,
            @Valid @ModelAttribute("newNote") NoteDto noteDto,
            BindingResult bindingResult,
            RedirectAttributes redirectAttributes) {

        if (bindingResult.hasErrors()) {
            redirectAttributes.addFlashAttribute("noteError", "Veuillez corriger les erreurs dans le formulaire");
            return "redirect:/notes/" + patientId;
        }

        try {
            PatientDto patient = gatewayServiceClient.getPatientById(patientId);

            noteDto.setId(null);
            noteDto.setPatId(patientId.intValue());
            noteDto.setPatient(patient.getFirstname());

            logger.info("Note to be added: {}", noteDto);

            gatewayServiceClient.createNote(noteDto);
            redirectAttributes.addFlashAttribute("success", "Note ajoutée avec succès");
            logger.info("Successfully added note for patient {}", patientId);

        } catch (Exception e) {
            logger.error("Error adding note for patient {}: {}", patientId, e.getMessage());
            redirectAttributes.addFlashAttribute("noteError", "Erreur lors de l'ajout de la note");
        }

        return "redirect:/notes/" + patientId;
    }

    /**
     * Updates an existing patient's information.
     * 
     * This endpoint handles POST requests to update patient data. It validates the
     * input,
     * updates the patient through the gateway service, and redirects back to the
     * patient's
     * notes page with appropriate success or error messages.
     * 
     * @param patientId          the unique identifier of the patient to update
     * @param patientDto         the patient data transfer object containing updated
     *                           information,
     *                           validated with @Valid annotation
     * @param bindingResult      the result of the validation process, contains any
     *                           validation errors
     * @param redirectAttributes attributes to be passed to the redirect target for
     *                           flash messages
     * @return redirect URL to the patient's notes page (/notes/{patientId})
     * 
     * @throws Exception if an error occurs during the patient update process
     * 
     *                   Flash attributes added:
     *                   - "success": confirmation message when update is successful
     *                   - "patientError": error message when validation fails or
     *                   update operation fails
     */
    @PostMapping("/patient/{id}/update")
    public String updatePatient(@PathVariable("id") Long patientId,
            @Valid @ModelAttribute("patient") PatientDto patientDto,
            BindingResult bindingResult,
            RedirectAttributes redirectAttributes) {

        if (bindingResult.hasErrors()) {
            redirectAttributes.addFlashAttribute("patientError", "Veuillez corriger les erreurs dans le formulaire");
            return "redirect:/notes/" + patientId;
        }

        try {
            gatewayServiceClient.updatePatient(patientId, patientDto);
            redirectAttributes.addFlashAttribute("success", "Informations patient mises à jour avec succès");
            logger.info("Successfully updated patient {}", patientId);

        } catch (Exception e) {
            logger.error("Error updating patient {}: {}", patientId, e.getMessage());
            redirectAttributes.addFlashAttribute("patientError", "Erreur lors de la mise à jour des informations");
        }

        return "redirect:/notes/" + patientId;
    }
}