package io.gmss.fiscad.controllers.infocad.metier;


import io.gmss.fiscad.entities.infocad.metier.Commentaire;
import io.gmss.fiscad.exceptions.*;
import io.gmss.fiscad.interfaces.infocad.metier.CommentaireService;
import io.gmss.fiscad.paylaods.ApiResponse;
import io.gmss.fiscad.paylaods.request.CommentaireRequest;
import io.gmss.fiscad.paylaods.request.SyncCommentaireRequest;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;

import java.time.LocalDateTime;
import java.util.List;

@RestController
@RequestMapping(value = "api/commentaire", produces = MediaType.APPLICATION_JSON_VALUE)
@SecurityRequirement(name = "bearer")
@Tag(name = "Commentaire")
@CrossOrigin(origins = "*")

public class CommentaireController {

    private final CommentaireService commentaireService;

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

    public CommentaireController(CommentaireService commentaireService) {
        this.commentaireService = commentaireService;
    }

    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @PostMapping("/create")
    public ResponseEntity<?> createcommentaire(@RequestBody @Valid @Validated Commentaire commentaire) {
        try {
            commentaire.setDateCommentaire(LocalDateTime.now());
            commentaire = commentaireService.createCommentaire(commentaire);
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaire, "Commentaire créé avec  succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @PutMapping("/update/{id}")
    public ResponseEntity<?> updatecommentaire(@PathVariable Long id, @RequestBody Commentaire commentaire) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.updateCommentaire(id, commentaire), "commentaire mis à jour avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @DeleteMapping("/delete/{id}")
    public ResponseEntity<?> deletecommentaire(@PathVariable Long id) {
        try {
            commentaireService.deleteCommentaire(id);
            return new ResponseEntity<>(
                    new ApiResponse<>(true, "Commentaire supprimé avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @GetMapping("/all")
    public ResponseEntity<?> getAllcommentaireList() {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.getCommentaireList(), "Liste des commentaires chargée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @GetMapping("/id/{id}")
    public ResponseEntity<?> getcommentaireById(@PathVariable Long id) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.getCommentaireById(id), "commentaire trouvée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @GetMapping("/nup/{nup}")
    public ResponseEntity<?> getcommentaireByNup(@PathVariable String nup) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.getCommentaireByNup(nup), "commentaire trouvée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @PostMapping("/enquete")
    public ResponseEntity<?> getcommentaireByEnquete(@RequestBody Commentaire commentaire) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.getCommentairesByEnqueteAndTerminal(commentaire.getIdEnquete(), commentaire.getTerminalId()), "Liste des commentaires chargée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @PostMapping("/enquete-and-state")
    //@ApiOperation(value = "Cette ressource permet d'avoir la liste de tous les commentaires d'une enquête avec le statut (lu ou non lu). Les champs a renseigner pour le payload sont idEnquete et lu")
    public ResponseEntity<?> getcommentaireByEnqueteAndStatut(@RequestBody Commentaire commentaire) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.getCommentairesByEnqueteAndLu(commentaire.getIdEnquete(), commentaire.isLu()), "Liste des commentaires chargée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @PostMapping("/all-by-params")
    //@ApiOperation(value = "Cette ressource permet d'avoir 4 résultats différents. \n 1 - Liste des commentaires non lus provenant du Web. \n 2 - Liste des commentaires lus provenant du Web \n 3 - Liste des commentaires non lus provenant du mobile. \n 4 - Liste des commentaires lus provenant du mobile. \n A savoir : Les variables Origine et lu sont à varier pour avoir le résultat")
    public ResponseEntity<?> getcommentaireByParams(@RequestBody CommentaireRequest commentaireRequest) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.getCommentairesByOrigineAndStateReadAndTerminalId(commentaireRequest.getOrigine(), commentaireRequest.isLu(), commentaireRequest.getTerminalId()), "Liste des commentaires chargée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }

    @PostMapping("synchronise/from-mobile")
    //@ApiOperation(value = "Cette ressource permet de synchroniser tous les commentaires effectués sur le mobile vers le backend.")
    public ResponseEntity<?> synchroniseCommentairesFromMobile(@RequestBody List<Commentaire> commentaires) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.saveAllCommentairesFromMobile(commentaires), "Liste des commentaires synchronisée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }

    @PostMapping("synchronise/from-web")
    //@ApiOperation(value = "Cette ressource permet d'avoir 4 résultats différents. \n 1 - Liste des commentaires non synchronisés provenant du Web. \n 2 - Liste des commentaires synchronisés provenant du Web \n 3 - Liste des commentaires non synchronisés provenant du mobile. \n 4 - Liste des commentaires synchronisés provenant du mobile. \n A savoir : Les variables Origine et Synchronise sont à varier pour avoir le résultat")
    public ResponseEntity<?> synchroniseCommentairesFromWeb(@RequestBody CommentaireRequest commentaireRequest) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.getCommentairesByOrigineAndStateSynchronizedAndTerminalId(commentaireRequest.getOrigine(), commentaireRequest.isSynchronise(), commentaireRequest.getTerminalId()), "Liste des commentaires chargée avec succès."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }
    @PreAuthorize("hasRole('ADMIN') or hasRole('SUPERVISEUR') or hasRole('ENQUETEUR')")
    @PostMapping("synchronise/notify-done-from-mobile")
    //@ApiOperation(value = "Cette ressource permet matérialiser coté backend les commentaires du WEB déjà synchronisé avec le MOBILE pour que les prochaines extractions ne prennent pas en compte cela. ")
    public ResponseEntity<?> notifyDoneSynchronizedFromMobile(@RequestBody List<SyncCommentaireRequest> syncCommentaireRequests) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, commentaireService.notifySynchronizedDoneFromMobile(syncCommentaireRequests), "Synchronisation terminée."),
                    HttpStatus.OK
            );
        } catch (HttpClientErrorException.MethodNotAllowed e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Method POST/GET is required."), HttpStatus.OK);
        } catch (NotFoundException | BadRequestException | MyFileNotFoundException | ResourceNotFoundException |
                 FileStorageException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, e.getMessage()), HttpStatus.OK);
        } catch (NullPointerException e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "Null value has been detected {" + e.getMessage() + "}."), HttpStatus.OK);
        } catch (Exception e) {
            logger.error(e.getLocalizedMessage());
            return new ResponseEntity<>(new ApiResponse(false, null, "An error has been occur and the content is {" + e.getMessage() + "}."), HttpStatus.OK);
        }
    }

}
