/*

 */
package com.braintreeocc.controllers;

import com.braintree.exceptions.BrainTreeInvalidAddressException;
import com.braintree.exceptions.InvalidPaymentInfoException;
import com.braintree.facade.impl.DefaultBrainTreeCheckoutFacade;
import com.braintree.hybris.data.ws.PriceValueWsDTO;
import com.google.common.collect.Lists;
import de.hybris.platform.commercefacades.user.UserFacade;
import de.hybris.platform.commercefacades.user.data.AddressData;
import de.hybris.platform.commercewebservicescommons.dto.user.AddressWsDTO;
import de.hybris.platform.util.PriceValue;
import de.hybris.platform.webservicescommons.cache.CacheControl;
import de.hybris.platform.webservicescommons.cache.CacheControlDirective;
import de.hybris.platform.webservicescommons.dto.error.ErrorListWsDTO;
import de.hybris.platform.webservicescommons.dto.error.ErrorWsDTO;
import de.hybris.platform.webservicescommons.swagger.ApiBaseSiteIdUserIdAndCartIdParam;
import de.hybris.platform.webservicescommons.swagger.ApiFieldsParam;
import de.hybris.platform.webservicescommons.util.YSanitizer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import javax.annotation.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/{baseSiteId}/users/{userId}/carts/{cartId}/braintree")
@CacheControl(directive = CacheControlDirective.NO_CACHE)
@Api(tags = "Braintree Checkout")
public class BraintreeCheckoutController extends BraintreeBaseCommerceController {

    @Resource(name = "brainTreeCheckoutFacade")
    private DefaultBrainTreeCheckoutFacade brainTreeCheckoutFacade;

    @Resource(name = "userFacade")
    private UserFacade userFacade;

    @Secured({"ROLE_CLIENT", "ROLE_CUSTOMERGROUP", "ROLE_GUEST", "ROLE_CUSTOMERMANAGERGROUP", "ROLE_TRUSTED_CLIENT",
        "ROLE_ANONYMOUS"})
    @PostMapping(value = "/express")
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(nickname = "express checkout", value = "process express checkout",
        notes = "Set delivery address, delivery mode and payment details for checkout")
    @ApiBaseSiteIdUserIdAndCartIdParam
    public HttpStatus processExpressCheckout(
        @ApiParam(value = "Request body parameter that contains" +
            "address data", required = true) @RequestBody final AddressWsDTO address,
        @ApiParam(value = "PaymentDetails id that needed use in checkout", required = true)
        @ApiFieldsParam @RequestParam final String paymentDetailsId)
        throws InvalidPaymentInfoException {
        if (brainTreeCheckoutFacade.getCheckoutCart().getDeliveryAddress() == null) {
            AddressData addressData = getDataMapper().map(address, AddressData.class);
            addressData = createAddressInternal(addressData);
            setCartDeliveryAddressInternal(addressData.getId());
        }
        brainTreeCheckoutFacade.removeDeliveryMode();
        brainTreeCheckoutFacade.setCheapestDeliveryModeForCheckout();
        setPaymentDetailsInternal(paymentDetailsId);
        if(brainTreeCheckoutFacade.getCheckoutCart().getDeliveryMode() == null){
            userFacade.removeAddress(brainTreeCheckoutFacade.getCheckoutCart().getDeliveryAddress());
            throw new BrainTreeInvalidAddressException("No country with the code");
        }
        return HttpStatus.OK;
    }

    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ResponseBody
    @ExceptionHandler({ BrainTreeInvalidAddressException.class })
    public ErrorListWsDTO handlePayPalConnectException(final BrainTreeInvalidAddressException ex)
    {
        return handleErrorInternal("ConversionError", ex.getMessage());
    }

    @Secured({"ROLE_CLIENT", "ROLE_CUSTOMERGROUP", "ROLE_GUEST", "ROLE_CUSTOMERMANAGERGROUP", "ROLE_TRUSTED_CLIENT",
        "ROLE_ANONYMOUS"})
    @GetMapping(value = "/countprice")
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation(nickname = "cunt delivery price", value = "count delivery price for current order and country")
    @ApiBaseSiteIdUserIdAndCartIdParam
    public PriceValueWsDTO countDeliveryPrice(
        @ApiParam(value = "Country code for delivery", required = true) @RequestParam final String countryCode) {
        final PriceValue priceValue = brainTreeCheckoutFacade.countDeliveryAddress(countryCode);
        final PriceValueWsDTO priceValueWsDTO = new PriceValueWsDTO();
        priceValueWsDTO.setValue(priceValue.getValue());
        priceValueWsDTO.setCurrency(priceValue.getCurrencyIso());
        return priceValueWsDTO;
    }

    protected ErrorListWsDTO handleErrorInternal(final String type, final String message)
    {
        final ErrorListWsDTO errorListDto = new ErrorListWsDTO();
        final ErrorWsDTO error = new ErrorWsDTO();
        error.setType(type.replace("Exception", "Error"));
        error.setMessage(YSanitizer.sanitize((message)));
        errorListDto.setErrors(Lists.newArrayList(error));
        return errorListDto;
    }

}
