package com.wishurgift.entry.controller;

import com.wishurgift.entry.security.Secured;
import com.wishurgift.entry.validator.TagValidator;
import com.wishurgift.service.ContactService;
import com.wishurgift.service.UserService;
import com.wishurgift.service.dto.UserDTO;
import com.wishurgift.service.dto.request.TagRequestDTO;
import com.wishurgift.utils.Constant;
import com.wishurgift.utils.JwtUtils;
import com.wishurgift.wrapper.Page;
import com.wishurgift.wrapper.Result;
import lombok.extern.slf4j.Slf4j;

import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;

@Slf4j
@Path("/contacts")
@Produces(MediaType.APPLICATION_JSON)
public class ContactController {

    @Inject
    private ContactService service;

    @Inject
    private UserService userService;

    @Inject
    private TagValidator tagValidator;

    @GET
    @Secured
    public Response list(@Context SecurityContext securityContext) {
        log.info("Begin ContactController list");
        // Recup utilisateur principale
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController list, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Recup les demandes effectuée par l'utilisateur connecté
        Page<UserDTO> page = service.getContact(principal);
        if (page == null) {
            log.info("End ContactController list, unable to get data");
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).trace(Constant.USER_NOT_FOUND).response();
        }
        log.info("End ContactController list");
        return Result.success().data(page).response();
    }

    @GET
    @Secured
    @Path("/page/{num}/{nb}")
    public Response page(@PathParam("num") int numPage, @PathParam("nb") int nbEltPage, @Context SecurityContext securityContext) {
        log.info("Begin ContactController page, numPage={} nbElt={}", numPage, nbEltPage);
        // Verif que le numero de page est valide
        if (numPage < 1) {
            log.info("End ContractController page, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.PAGE_NUMBER_INVALID).response();
        }
        // Recup utilisateur principale
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController page, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Recup les demandes effectuée par l'utilisateur connecté
        Page<UserDTO> page = service.getContact(numPage, nbEltPage, principal);
        if (page == null) {
            log.info("End ContactController page, unable to get data");
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).trace(Constant.USER_NOT_FOUND).response();
        }
        log.info("End ContactController page");
        return Result.success().data(page).response();
    }

    @GET
    @Secured
    @Path("/request")
    public Response requestList(@Context SecurityContext securityContext) {
        log.info("Begin ContactController requestList");
        // Recup utilisateur principale
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController requestList, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Recup les demandes effectuée par l'utilisateur connecté
        Page<UserDTO> page = service.getRequest(principal);
        if (page == null) {
            log.info("End ContactController requestList, unable to get data");
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).trace(Constant.USER_NOT_FOUND).response();
        }
        log.info("End ContactController requestList");
        return Result.success().data(page).response();
    }

    @GET
    @Secured
    @Path("/request/page/{num}/{nb}")
    public Response requestPage(@PathParam("num") int numPage, @PathParam("nb") int nbEltPage, @Context SecurityContext securityContext) {
        log.info("Begin ContactController requestPage, numPage={} nbElt={}", numPage, nbEltPage);
        // Verif que le numero de page est valide
        if (numPage < 1) {
            log.info("End ContractController requestPage, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.PAGE_NUMBER_INVALID).response();
        }
        // Recup utilisateur principale
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController requestPage, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Recup les demandes effectuée par l'utilisateur connecté
        Page<UserDTO> page = service.getRequest(numPage, nbEltPage, principal);
        if (page == null) {
            log.info("End ContactController requestPage, unable to get data");
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).trace(Constant.USER_NOT_FOUND).response();
        }
        log.info("End ContactController requestPage");
        return Result.success().data(page).response();
    }

    @GET
    @Secured
    @Path("/pending")
    public Response pendingList(@Context SecurityContext securityContext) {
        log.info("Begin ContactController pendingList");
        // Recup utilisateur principale
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController pendingList, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Recup les demandes effectuée par l'utilisateur connecté
        Page<UserDTO> page = service.getPending(principal);
        if (page == null) {
            log.info("End ContactController pendingList, unable to get data");
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).trace(Constant.USER_NOT_FOUND).response();
        }
        log.info("End ContactController pendingList");
        return Result.success().data(page).response();
    }

    @GET
    @Secured
    @Path("/pending/page/{num}/{nb}")
    public Response pendingPage(@PathParam("num") int numPage, @PathParam("nb") int nbEltPage, @Context SecurityContext securityContext) {
        log.info("Begin ContactController pendingPage, numPage={} nbElt={}", numPage, nbEltPage);
        // Verif que le numero de page est valide
        if (numPage < 1) {
            log.info("End ContractController pendingPage, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.PAGE_NUMBER_INVALID).response();
        }
        // Recup utilisateur principale
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController pendingPage, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Recup les demandes effectuée par l'utilisateur connecté
        Page<UserDTO> page = service.getPending(numPage, nbEltPage, principal);
        if (page == null) {
            log.info("End ContactController pendingPage, unable to get data");
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).trace(Constant.USER_NOT_FOUND).response();
        }
        log.info("End ContactController pendingPage");
        return Result.success().data(page).response();
    }

    @POST
    @Secured
    public Response add(TagRequestDTO data, @Context SecurityContext securityContext) {
        log.info("Begin ContactController add, tag={}", data.getTag());
        // Verification des données
        if (tagValidator.isNotValid(data)) {
            log.info("End ContractController add, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(tagValidator.getAllErrors()).response();
        }
        // Recup utilisateur principale
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController delete, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Ajout contact
        UserDTO contact = service.add(principal, data);
        if (contact == null) {
            log.info("End ContactController add, unauthorized action");
            return Result.error().data(Result.Error.UNAUTHORIZED).trace(Constant.CONTACT_REQUEST_ALREADY_EXIST).response();
        }
        log.info("End ContactController add");
        return Result.success().data(contact).response();
    }

    @DELETE
    @Secured
    @Path("/{user}")
    public Response delete(@PathParam("user") int userid, @Context SecurityContext securityContext) {
        log.info("Begin ContactController delete, user={}", userid);
        if (userid < 1) {
            log.info("End ContactController delete, invalid request (user id < 1)");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        // Recup utilisateur principale et le contact
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End ContactController delete, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        UserDTO contact = userService.getById(userid);
        if (contact == null) {
            log.info("End ContactController delete, invalid request (user not found)");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        log.info("Contact {}", principal.getTag());
        // Supprime
        service.remove(principal, contact);
        log.info("End ContactController delete");
        return Result.success().response();
    }

}
