package com.wishurgift.entry.controller;

import com.wishurgift.entry.security.Connected;
import com.wishurgift.entry.security.Secured;
import com.wishurgift.entry.validator.ElementAddValidator;
import com.wishurgift.entry.validator.WishlistAddValidator;
import com.wishurgift.entry.validator.WishlistUpdateValidator;
import com.wishurgift.service.WishlistService;
import com.wishurgift.service.dto.*;
import com.wishurgift.service.dto.request.ElementRequestDTO;
import com.wishurgift.service.dto.request.WishlistRequestDTO;
import com.wishurgift.utils.Constant;
import com.wishurgift.utils.JwtUtils;
import com.wishurgift.utils.ResponseUtils;
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("/wishlists")
@Produces(MediaType.APPLICATION_JSON)
public class WishlistController {

    @Inject
    private WishlistService service;

    @Inject
    private WishlistAddValidator wishlistAddValidator;

    @Inject
    private WishlistUpdateValidator wishlistUpdateValidator;

    @Inject
    private ElementAddValidator elementAddValidator;

    @GET
    @Connected
    @Path("/{id}")
    public Response getWishlist(@PathParam("id") long id, @Context SecurityContext securityContext) {
        log.info("Begin WishlistController getWishlist, id={}", id);
        // Verification données
        if (id < 1) {
            log.info("End WishlistController getWishlist, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        // Recup liste
        WishlistDTO wishlist = service.getWishlist(id, principal);
        if (wishlist == null) {
            log.info("End WishlistController getWishlist, unable to get data");
            return Result.error().data(Result.Error.UNABLE_TO_GET_DATA).response();
        }
        log.info("End WishlistController getWishlist");
        return Result.success().data(wishlist).response();
    }

    @GET
    @Secured
    @Path("/{id}/shared")
    public Response getShared(@PathParam("id") long id, @Context SecurityContext securityContext) {
        log.info("Begin WishlistController getShared, id={}", id);
        // Verification données
        if (id < 1) {
            log.info("End WishlistController getShared, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End WishlistController getShared, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Recup liste
        Page<UserLightDTO> users = service.sharedWith(principal, id);
        if (users == null) {
            log.info("End WishlistController getShared, unauthorized");
            return Result.error().data(Result.Error.UNAUTHORIZED).response();
        }
        log.info("End WishlistController getShared");
        return Result.success().data(users).response();
    }

    @POST
    @Secured
    public Response add(WishlistRequestDTO request, @Context SecurityContext securityContext) {
        log.info("Begin WishlistController add, name={} public={}", request.getName(), request.isPublic());
        // Verification données
        if (wishlistAddValidator.isNotValid(request)) {
            log.info("End WishlistController add, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(wishlistAddValidator.getAllErrors()).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End WishlistController add, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Ajout
        WishlistHeaderDTO wishlist = service.add(principal, request);
        if (wishlist == null) {
            log.info("End WishlistController add, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        log.info("End WishlistController add");
        return Result.success().data(wishlist).response();
    }

    @POST
    @Secured
    @Path("/{id}/element")
    public Response element(@PathParam("id") long id, ElementRequestDTO request, @Context SecurityContext securityContext) {
        log.info("Begin WishController element, list={} element={}", id, request);
        // Verification données
        if (id < 1) {
            log.info("End WishlistController element, invalid id");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        if (elementAddValidator.isNotValid(request)) {
            log.info("End WishlistController element, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(elementAddValidator.getAllErrors()).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End WishlistController element, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Ajout de l'element
        ElementDTO element = service.addElement(principal, id, request);
        if (element == null) {
            log.info("End WishlistController element, unauthorized");
            return Result.error().data(Result.Error.UNAUTHORIZED).response();
        }
        log.info("End WishlistController element");
        return Result.success().data(element).response();
    }

    @PUT
    @Secured
    @Path("/{id}")
    public Response update(@PathParam("id") long id, WishlistRequestDTO request, @Context SecurityContext securityContext) {
        log.info("Begin WishlistController update, id={}", id);
        // Verification données
        if (id < 1) {
            log.info("End WishlistController remove, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        if (wishlistUpdateValidator.isNotValid(request)) {
            log.info("End WishlistController update, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(wishlistUpdateValidator.getAllErrors()).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End WishlistController update, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // MaJ de la liste
        Result result = service.update(principal, id, request);
        if (result.isSuccess()) {
            log.info("End WishlistController update");
        } else {
            log.info("End WishlistController update, error");
        }
        return ResponseUtils.make(result);
    }

    @PUT
    @Secured
    @Path("/{id}/share/{user}")
    public Response share(@PathParam("id") long id, @PathParam("user") long userId, @Context SecurityContext securityContext) {
        log.info("Begin WishlistController share, id={} user={}", id, userId);
        // Verification données
        if (id < 1) {
            log.info("End WishlistController share, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        if (userId < 1) {
            log.info("End WishlistController share, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End WishlistController share, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Partage
        if (!service.share(principal, id, userId)) {
            log.info("End WishlistController share, unauthorized");
            return Result.error().data(Result.Error.UNAUTHORIZED).response();
        }
        log.info("End WishlistController share");
        return Result.success().response();
    }

    @DELETE
    @Secured
    @Path("/{id}")
    public Response remove(@PathParam("id") long id, @Context SecurityContext securityContext) {
        log.info("Begin WishlistController remove, id={}", id);
        // Verification données
        if (id < 1) {
            log.info("End WishlistController remove, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End WishlistController remove, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // MaJ de la liste
        Result result = service.remove(principal, id);
        if (result.isSuccess()) {
            log.info("End WishlistController remove");
        } else {
            log.info("End WishlistController remove, error");
        }
        return ResponseUtils.make(result);
    }

    @DELETE
    @Secured
    @Path("/{id}/share/{user}")
    public Response unshare(@PathParam("id") long id, @PathParam("user") long userId, @Context SecurityContext securityContext) {
        log.info("Begin WishlistController unshare, id={} user={}", id, userId);
        // Verification données
        if (id < 1) {
            log.info("End WishlistController unshare, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        if (userId < 1) {
            log.info("End WishlistController unshare, invalid request");
            return Result.error().data(Result.Error.INVALID_REQUEST).trace(Constant.INVALID_ID).response();
        }
        // Recup utilisateur connecté
        UserDTO principal = JwtUtils.getUser(securityContext.getUserPrincipal());
        if (principal == null) {
            log.info("End WishlistController unshare, unable to connect");
            return Result.error().data(Result.Error.UNABLE_TO_CONNECT).trace(Constant.USER_NOT_FOUND).response();
        }
        // Partage
        if (!service.unshare(principal, id, userId)) {
            log.info("End WishlistController unshare, unauthorized");
            return Result.error().data(Result.Error.UNAUTHORIZED).response();
        }
        log.info("End WishlistController unshare");
        return Result.success().response();
    }

}
