package com.braintree.populators;

import com.braintree.command.result.BrainTreeBillingAddressResult;
import com.braintree.enums.BrainTreeCardType;
import com.braintree.hybris.data.graphql.commands.response.BrainTreeAddress;
import com.braintree.hybris.data.graphql.commands.response.BraintreePaymentMethodData;
import com.braintree.hybris.data.graphql.commands.response.BrainTreePaymentMethodDetails;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintree.payment.info.service.BraintreePaymentInfoService;
import de.hybris.platform.converters.Populator;
import de.hybris.platform.core.model.user.AddressModel;
import de.hybris.platform.servicelayer.dto.converter.ConversionException;
import de.hybris.platform.servicelayer.dto.converter.Converter;

/**
 * Populates BrainTreePaymentInfoModel from BrainTreePaymentMethod.
 */
public class BraintreePaymentMethodDetailsToModelPopulator implements
        Populator<BraintreePaymentMethodData, BrainTreePaymentInfoModel> {

    private BraintreePaymentInfoService braintreePaymentInfoService;
    private Converter<BrainTreeAddress, BrainTreeBillingAddressResult> graphQLAddressToAddressResult;
    private Converter<BrainTreeBillingAddressResult, AddressModel> addressResultToAddressModelConverter;

    @Override
    public void populate(BraintreePaymentMethodData source, BrainTreePaymentInfoModel target)
            throws ConversionException {
        if (isSourceAndTargetNotNull(source, target)) {

            target.setPaymentMethodToken(source.getLegacyId());
            target.setPaymentMethodGraphQLToken(source.getId());

            final BrainTreePaymentMethodDetails details = source.getDetails();

            if (details != null) {
                String originType = null;
                if (details.getOrigin() != null) {
                    originType = details.getOrigin().getType();
                }

                final String paymentProvider = braintreePaymentInfoService
                        .getPaymentProviderByDetailsAndOrigin(details.get__typename(), originType);
                final String imageSource = braintreePaymentInfoService
                        .getImageSourceByPaymentProviderAndCardType(paymentProvider, details.getBrandCode());
                target.setPaymentProvider(paymentProvider);
                target.setImageSource(imageSource);

                if (isBinAndLast4FiguresNotNull(details)) {
                    final String number = String.format("%s******%s", details.getBin(), details.getLast4());
                    target.setPaymentInfo(number);
                    target.setCardNumber(number);
                }

                target.setCreatedAt(source.getCreatedAt().getTime());
                if (source.getCustomer() != null) {
                    target.setCustomerId(source.getCustomer().getLegacyId());
                }
                if (details.getBrandCode() != null) {
                    target.setCardType(BrainTreeCardType.valueOf(details.getBrandCode()));
                }
                target.setCardholderName(details.getCardholderName());
                target.setExpirationMonth(details.getExpirationMonth());
                target.setExpirationYear(details.getExpirationYear());

                if (details.getBillingAddress() != null) {
                    final BrainTreeBillingAddressResult addressResult = graphQLAddressToAddressResult
                            .convert(details.getBillingAddress());
                    target.setBillingAddress(addressResultToAddressModelConverter.convert(addressResult));
                }
            }
        }
    }

    private boolean isBinAndLast4FiguresNotNull(BrainTreePaymentMethodDetails details) {
        return details.getBin() != null && details.getLast4() != null;
    }

    private boolean isSourceAndTargetNotNull(BraintreePaymentMethodData source, BrainTreePaymentInfoModel target) {
        return source != null && target != null;
    }

    public void setBraintreePaymentInfoService(
            BraintreePaymentInfoService braintreePaymentInfoService) {
        this.braintreePaymentInfoService = braintreePaymentInfoService;
    }


    public void setGraphQLAddressToAddressResult(
            Converter<BrainTreeAddress, BrainTreeBillingAddressResult> graphQLAddressToAddressResult) {
        this.graphQLAddressToAddressResult = graphQLAddressToAddressResult;
    }

    public void setAddressResultToAddressModelConverter(
            Converter<BrainTreeBillingAddressResult, AddressModel> addressResultToAddressModelConverter) {
        this.addressResultToAddressModelConverter = addressResultToAddressModelConverter;
    }
}
