package org.kuorum.rest.controller.user;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.kuorum.provider.mongo.model.cause.Cause;
import org.kuorum.provider.mongo.model.kuorumUser.KuorumUser;
import org.kuorum.rest.exception.NotFoundException;
import org.kuorum.rest.mapper.orika.OrikaBeanMapper;
import org.kuorum.rest.model.tag.CauseRSDTO;
import org.kuorum.rest.model.tag.SupportedCauseRSDTO;
import org.kuorum.rest.security.helper.AuthenticationFacade;
import org.kuorum.service.causes.CausesService;
import org.kuorum.service.causes.SuggestCausesService;
import org.kuorum.service.causes.exception.CauseException;
import org.kuorum.service.user.KuorumUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Operation causes
 */
@RestController()
@RequestMapping("/api/user/{userId}/causes")
@Api(value = "User causes operations")
public class UserCausesOperationsController {

    private static final Logger log = LoggerFactory.getLogger(UserCausesOperationsController.class);


    @Autowired
    CausesService causesService;

    @Autowired
    SuggestCausesService suggestCausesService;

    @Autowired
    KuorumUserService kuorumUserService;

    @Autowired
    AuthenticationFacade authenticationFacade;

    @Autowired
    private OrikaBeanMapper mapper;

    @RequestMapping(value = "/support", method = RequestMethod.GET)
    @ApiOperation(
            value = "Returns the supported causes by the user ordered by citizens support")
    @ApiResponses(value =
    @ApiResponse(code = 404, message = "User not found")
    )
    public List<CauseRSDTO> getUserSupportedCauses(@PathVariable String userId) throws NotFoundException {

        KuorumUser user = kuorumUserService.findUser(userId);
        if (user == null){
            throw new NotFoundException();
        }

        List<Cause> causes = causesService.findSupportedCausesByUser(user);
        return causes.stream().map(r -> mapper.map(r, CauseRSDTO.class)).collect(Collectors.toList());
    }


    @RequestMapping(value = "/support/{causeName}", method = RequestMethod.GET)
    @ApiOperation(value = "Returns the status (supported or unsupported) of the cause for the user")
    @ApiResponses(value =
    @ApiResponse(code = 404, message = "User or cause not found")
    )
    public SupportedCauseRSDTO getSupportCause(@PathVariable String causeName, @PathVariable String userId) throws NotFoundException, UnsupportedEncodingException {

        KuorumUser user = kuorumUserService.findUser(userId);
        causeName = URLDecoder.decode(causeName, "UTF-8");
        Cause cause = causesService.findCause(causeName, authenticationFacade.getDomain());
        if (cause == null || user == null){
            log.info("Cause found {} searched by causeName = {}", cause, causeName);
            log.info("User found {} searched by id= {}", user, userId);
            throw new NotFoundException();
        }
        SupportedCauseRSDTO supportedCauseRSDTO = mapper.map(cause, SupportedCauseRSDTO.class);
        supportedCauseRSDTO.setUserId(userId);
        supportedCauseRSDTO.setSupported(causesService.isCauseSupportedBy(cause, user));
        return supportedCauseRSDTO;
    }

    @RequestMapping(value = "/support/{causeName}", method = RequestMethod.PUT)
    @ApiOperation(
            value = "Supports the cause by the user",
            notes = "If the user is already supporting the cause, the operation has no effect")
    @ApiResponses(value =
    @ApiResponse(code = 404, message = "User or cause not found")
    )
    public SupportedCauseRSDTO supportCause(@PathVariable String causeName, @PathVariable String userId) throws NotFoundException, CauseException, UnsupportedEncodingException {

        KuorumUser user = kuorumUserService.findUser(userId);
        if (user == null){
            throw new NotFoundException();
        }
        causeName = URLDecoder.decode(causeName, "UTF-8");
        Cause cause = causesService.supportCause(causeName, user);
        if (cause == null){
            throw new NotFoundException();
        }
        SupportedCauseRSDTO supportedCauseRSDTO = mapper.map(cause, SupportedCauseRSDTO.class);
        supportedCauseRSDTO.setUserId(userId);
        supportedCauseRSDTO.setSupported(true);
        return supportedCauseRSDTO;
    }

    @RequestMapping(value = "/support/{causeName}", method = RequestMethod.DELETE)
    @ApiResponses(value =
    @ApiResponse(code = 404, message = "User or cause not found")
    )
    public SupportedCauseRSDTO unSupportCause(@PathVariable String causeName, @PathVariable String userId) throws NotFoundException, UnsupportedEncodingException {
        KuorumUser user = kuorumUserService.findUser(userId);
        if (user == null){
            throw new NotFoundException();
        }
        causeName = URLDecoder.decode(causeName, "UTF-8");
        Cause cause = causesService.unsupportCause(causeName, user);
        if (cause == null){
            throw new NotFoundException();
        }
        SupportedCauseRSDTO supportedCauseRSDTO = mapper.map(cause, SupportedCauseRSDTO.class);
        supportedCauseRSDTO.setUserId(userId);
        supportedCauseRSDTO.setSupported(false);
        return supportedCauseRSDTO;
    }
//
//    @RequestMapping(value = "/defend", method = RequestMethod.GET)
//    @ApiOperation(
//            value = "Returns the defended causes by the politicians ordered by citizens support")
//    @ApiResponses(value =
//    @ApiResponse(code = 404, message = "User not found")
//    )
//    public List<CauseRSDTO> getPoliticianDefendingCauses(@PathVariable String userId) throws NotFoundException {
//
//        KuorumUser user = kuorumUserService.findUser(userId);
//        if (user == null){
//            throw new NotFoundException();
//        }
//
//        List<Cause> causes = causesService.findCausesDefendedByPolitician(user);
//        return causes.stream().map(r -> mapper.map(r, CauseRSDTO.class)).collect(Collectors.toList());
//    }
//
//    @RequestMapping(value = "/defend/{causeName}", method = RequestMethod.PUT)
//    @ApiOperation(
//            value = "An user defends a cause.",
//            notes = "If the user is already defending the cause, the operation has no effect")
//    @ApiResponses(value =
//    @ApiResponse(code = 404, message = "User or cause not found")
//    )
//    public SupportedCauseRSDTO defendCause(@PathVariable String causeName, @PathVariable String userId) throws NotFoundException, CauseException {
//
//        KuorumUser user = kuorumUserService.findUser(userId);
//        if (user == null){
//            throw new NotFoundException();
//        }
//        Cause cause = causesService.defendCause(causeName, user);
//        if (cause == null){
//            throw new NotFoundException();
//        }
//        SupportedCauseRSDTO supportedCauseRSDTO = mapper.map(cause, SupportedCauseRSDTO.class);
//        supportedCauseRSDTO.setUserId(userId);
//        supportedCauseRSDTO.setSupported(true);
//        return supportedCauseRSDTO;
//    }
//
//    @RequestMapping(value = "/defend/{causeName}", method = RequestMethod.DELETE)
//    @ApiOperation(value = "A politician withdraw a cause.")
//    @ApiResponses(value =
//    @ApiResponse(code = 404, message = "User or cause not found")
//    )
//    public SupportedCauseRSDTO withdrawCause(@PathVariable String causeName, @PathVariable String userId) throws NotFoundException, CauseException {
//        KuorumUser user = kuorumUserService.findUser(userId);
//        if (user == null){
//            throw new NotFoundException();
//        }
//        Cause cause = causesService.withdrawCause(causeName, user);
//        if (cause == null){
//            throw new NotFoundException();
//        }
//        SupportedCauseRSDTO supportedCauseRSDTO = mapper.map(cause, SupportedCauseRSDTO.class);
//        supportedCauseRSDTO.setUserId(userId);
//        supportedCauseRSDTO.setSupported(false);
//        return supportedCauseRSDTO;
//    }

}
