package io.gmss.fiscad.controllers.user;


import io.gmss.fiscad.entities.user.DemandeReinitialisationMP;
import io.gmss.fiscad.entities.user.User;
import io.gmss.fiscad.enums.UserRole;
import io.gmss.fiscad.exceptions.*;
import io.gmss.fiscad.interfaces.user.DemandeReinitialisationMPService;
import io.gmss.fiscad.interfaces.user.RoleService;
import io.gmss.fiscad.interfaces.user.UserService;
import io.gmss.fiscad.paylaods.ApiResponse;
import io.gmss.fiscad.paylaods.DemandeReinitialisationMPResponse;
import io.gmss.fiscad.security.CurrentUser;
import io.gmss.fiscad.security.UserPrincipal;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;

@RestController
@RequestMapping(value = "api/demande-reinitialisation-mp", produces = MediaType.APPLICATION_JSON_VALUE)
@SecurityRequirement(name = "bearer")
@Tag(name = "Demande de réinitialisation mot de passe")
@CrossOrigin(origins = "*")
public class DemandeReinitialisationMPController {

    private final DemandeReinitialisationMPService demandeReinitialisationMPService;
    private static final Logger logger = LoggerFactory.getLogger(DemandeReinitialisationMPController.class);
    private final UserService userService;
    private final RoleService roleService;

    public DemandeReinitialisationMPController(DemandeReinitialisationMPService demandeReinitialisationMPService, UserService userService, RoleService roleService) {
        this.demandeReinitialisationMPService = demandeReinitialisationMPService;
        this.userService = userService;
        this.roleService = roleService;
    }

    @GetMapping("/create")
    public ResponseEntity<?> createDemandeReinitialisationMP(@RequestParam String usernamrOrEmail) {
        try {
            demandeReinitialisationMPService.createDemandeReinitialisationMP(usernamrOrEmail);
            return new ResponseEntity<>(
                    new ApiResponse<>(true, "Demande Reinitialisation mot de passe 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);
        }
    }

    @PutMapping("/update/{id}")
    public ResponseEntity<?> updateDemandeReinitialisationMP(@PathVariable Long id, @RequestBody DemandeReinitialisationMP demandeReinitialisationMP) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, demandeReinitialisationMPService.updateDemandeReinitialisationMP(id, demandeReinitialisationMP), "DemandeReinitialisationMP 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);
        }
    }

    @DeleteMapping("/delete/{id}")
    public ResponseEntity<?> deleteDemandeReinitialisationMPr(@PathVariable Long id) {
        try {
            demandeReinitialisationMPService.deleteDemandeReinitialisationMP(id);
            return new ResponseEntity<>(
                    new ApiResponse<>(true, "Demande de Reinitialisation de mot de passe 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);
        }
    }

    @GetMapping("/all")
    public ResponseEntity<?> getAllDemandeReinitialisationMPList(@CurrentUser UserPrincipal userPrincipal) {
        try {

            User user = userPrincipal.getUser();

            if (user.getRoles().stream().anyMatch(r -> r.getNom().equals(UserRole.ROLE_ADMIN))) {
                return new ResponseEntity<>(
                        new ApiResponse<>(true, demandeReinitialisationMPService.getDemandeReinitialisationMPList(), "Liste des demande de Reinitialisation chargée avec succès."),
                        HttpStatus.OK
                );
            } else {
                if (user.getStructure() == null) {
                    return new ResponseEntity<>(
                            new ApiResponse<>(false, "Cet utilisateur n'est pas dans une structure; on ne peut donc pas afficher les demandes de réinitialisation de mot de passe."),
                            HttpStatus.OK
                    );
                } else {
                    return new ResponseEntity<>(
                            new ApiResponse<>(true, demandeReinitialisationMPService.getDemandeReinitialisationMPNonTraiteList(user.getStructure()), "Liste des demande de Reinitialisation chargée avec succès."),
                            HttpStatus.OK
                    );
                }
            }
//            }else {
//                if (user.getStructure() == null) {
//                    return new ResponseEntity<>(
//                            new ApiResponse<>(false, "Cet utilisateur n'est pas dans une structure; on ne peut donc pas afficher les demandes de réinitialisation de mot de passe."),
//                            HttpStatus.OK
//                    );
//                } else {
//                    return new ResponseEntity<>(
//                            new ApiResponse<>(true, demandeReinitialisationMPService.getDemandeReinitialisationMPNonTraiteList(user.getStructure()), "Liste des demande de Reinitialisation 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);
        }

    }

    @GetMapping("/all-paged")
    public ResponseEntity<?> getAllDemandeReinitialisationMPPaged(@RequestParam int pageNo, @RequestParam int pageSize) {
        try {
            Pageable pageable = PageRequest.of(pageNo, pageSize);

            return new ResponseEntity<>(
                    new ApiResponse<>(true, demandeReinitialisationMPService.getDemandeReinitialisationMPList(pageable), "Liste des demandeReinitialisationMP 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);
        }
    }

    @GetMapping("/id/{id}")
    public ResponseEntity<?> getDemandeReinitialisationMPById(@PathVariable Long id) {
        try {
            return new ResponseEntity<>(
                    new ApiResponse<>(true, demandeReinitialisationMPService.getDemandeReinitialisationMPById(id), "DemandeReinitialisationMP trouvé 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);
        }
    }

    @GetMapping("/reset")
    public ResponseEntity<?> traiterDemande(@RequestParam Long id, @RequestParam String password) {
        try {
            DemandeReinitialisationMP demandeReinitialisationMP = demandeReinitialisationMPService.traiterDemandeReinitialisation(id, password);

            return new ResponseEntity<>(
                    new ApiResponse<>(true,
                            new DemandeReinitialisationMPResponse(
                                    userService.getUserResponseFromUser(demandeReinitialisationMP.getUser()),
                                    demandeReinitialisationMP.getEtatDemande()
                            ),
                            "Traitement effectué 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);
        }
    }
}
