package com.braintree.util;

import static com.braintree.constants.BraintreeConstants.CARD_NUMBER_MASK;

import com.braintree.command.result.BrainTreeBillingAddressResult;
import com.braintree.command.result.BrainTreeCreatePaymentMethodResult;
import com.braintree.command.result.BrainTreePaymentDetailsResult;
import com.braintree.constants.BraintreeConstants.PayPalIntent;
import com.braintree.enums.BrainTreePaymentMethod;
import com.braintree.hybris.data.graphql.commands.response.BrainTreePaymentMethodDetails;
import com.braintree.model.BrainTreePaymentInfoModel;
import com.braintreegateway.Address;
import de.hybris.platform.servicelayer.dto.converter.ConversionException;

import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Optional;

public class BrainTreeUtils {

    private static final String PAY_PAL_ACCOUNT_DETAILS = "PayPalAccountDetails";
    private static final String VENMO_ACCOUNT_DETAILS = "VenmoAccountDetails";
    private static final String US_BANK_ACCOUNT_DETAILS = "UsBankAccountDetails";
    private static final String CREDIT_CARD_DETAILS = "CreditCardDetails";
    private static final String VISA_CHECKOUT = "VISA_CHECKOUT";
    private static final String APPLE_PAY = "APPLE_PAY";
    private static final String GOOGLE_PAY = "GOOGLE_PAY";

    private BrainTreeUtils() {
        //empty to avoid instantiating this constant class
    }

    public static boolean isCreditCardPayment(String paymentProvider) {
        return BrainTreePaymentMethod.CREDITCARD.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isSavedPaymentSupportThreeDS(String paymentProvider){
        return  isCreditCardPayment(paymentProvider)
                || isGooglePayment(paymentProvider)
                || isSrcPayment(paymentProvider);
    }

    public static boolean isPaymentSupportThreeDS(String paymentProvider){
        return  isCreditCardPayment(paymentProvider)
                || isGooglePayment(paymentProvider);
    }

    public static boolean isPayPalPayment(String paymentProvider) {
        return BrainTreePaymentMethod.BRAINTREEPAYPALEXPRESS.getCode().equalsIgnoreCase(paymentProvider)
            || BrainTreePaymentMethod.PAYPALACCOUNT.getCode().equalsIgnoreCase(paymentProvider)
            || BrainTreePaymentMethod.PAYPAL.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isUsBankAccountPayment(String paymentProvider) {
        return BrainTreePaymentMethod.USBANKACCOUNT.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isVenmoPayment(String paymentProvider) {
        return BrainTreePaymentMethod.VENMOACCOUNT.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isGooglePayment(String paymentProvider) {
        return BrainTreePaymentMethod.ANDROIDPAYCARD.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isSrcPayment(String paymentProvider) {
        return BrainTreePaymentMethod.VISACHECKOUTCARD.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isApplePayPayment(String paymentProvider) {
        return BrainTreePaymentMethod.APPLEPAYCARD.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isLPMPayment(String paymentProvider) {
        return BrainTreePaymentMethod.LOCALPAYMENT.getCode().equalsIgnoreCase(paymentProvider);
    }

    public static boolean isIntentSale(String intent) {
        return PayPalIntent.PAYPAL_INTENT_SALE.equalsIgnoreCase(intent);
    }

    public static boolean isIntentAuthorize(String intent) {
        return PayPalIntent.PAYPAL_INTENT_AUTHORIZE.equalsIgnoreCase(intent);
    }

    public static String formatCardNumber(String last4) {
        return String.format(CARD_NUMBER_MASK, last4);
    }

    public static BrainTreeBillingAddressResult convertRestBrainTreeAddress(Address source)
        throws ConversionException {
        BrainTreeBillingAddressResult addressResult = new BrainTreeBillingAddressResult();
        if(source != null) {
            addressResult.setAddressId(source.getId());
            addressResult.setCompany(source.getCompany());
            addressResult.setCountyCode(source.getCountryCodeAlpha2());
            addressResult.setCountyCodeAlpha3(source.getCountryCodeAlpha3());
            addressResult.setStreetAddress(source.getStreetAddress());
            addressResult.setExtendedAddress(source.getExtendedAddress());
            addressResult.setRegion(source.getRegion());
            addressResult.setLocality(source.getLocality());
            addressResult.setPostalCode(source.getPostalCode());
            addressResult.setPhone(source.getPhoneNumber());
            addressResult.setFirstName(source.getFirstName());
            addressResult.setLastName(source.getLastName());
        }
        return addressResult;
    }

    public static BrainTreeCreatePaymentMethodResult convertPaymentDetailsToPaymentMethodResult(
            BrainTreePaymentDetailsResult paymentMethod) {
        BrainTreeCreatePaymentMethodResult result = new BrainTreeCreatePaymentMethodResult();
        result.setPaymentProvider(paymentMethod.getPaymentProvider());
        result.setPaymentMethodToken(paymentMethod.getPaymentMethodToken());
        result.setPaymentMethodGraphQLToken(paymentMethod.getPaymentMethodGraphQLToken());
        result.setImageSource(paymentMethod.getImageUrl());
        result.setEmail(paymentMethod.getEmail());
        result.setSuccess(Boolean.TRUE);
        result.setCardType(paymentMethod.getCardType());
        result.setExpirationMonth(paymentMethod.getExpirationMonth());
        result.setExpirationYear(paymentMethod.getExpirationYear());
        result.setCardNumber(paymentMethod.getCardNumber());
        result.setLast4(paymentMethod.getLast4());
        result.setCardholderName(paymentMethod.getCardholderName());
        result.setVerified(paymentMethod.getVerified());
        if(paymentMethod.getRoutingNumber() != null){
            result.setRoutingNumber(paymentMethod.getRoutingNumber());
        }
        return result;
    }

    public static long getReminderMonthToExpire(BrainTreePaymentInfoModel paymentInfoModel){
        final String expiryDateInStr = String.format("%s/%s",
                paymentInfoModel.getExpirationMonth(), paymentInfoModel.getExpirationYear());
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/yyyy");
        final YearMonth expiryDate = YearMonth.parse(expiryDateInStr,  formatter);
        return ChronoUnit.MONTHS.between(YearMonth.now(), expiryDate);
    }

    public static Optional<BrainTreePaymentMethod> determinePaymentProvider(BrainTreePaymentMethodDetails paymentMethodDetails) {
        String paymentDetailsTypeName = paymentMethodDetails.get__typename();

        Optional<BrainTreePaymentMethod> result = Optional.empty();

        if (paymentDetailsTypeName.equals(PAY_PAL_ACCOUNT_DETAILS)) {
            result = Optional.of(BrainTreePaymentMethod.PAYPALACCOUNT);
        } else if (paymentDetailsTypeName.equals(VENMO_ACCOUNT_DETAILS)) {
            result = Optional.of(BrainTreePaymentMethod.VENMOACCOUNT);
        }else if (paymentDetailsTypeName.equals(US_BANK_ACCOUNT_DETAILS)) {
            result = Optional.of(BrainTreePaymentMethod.USBANKACCOUNT);
        }else if (paymentDetailsTypeName.equals(CREDIT_CARD_DETAILS)) {
            if (paymentMethodDetails.getOrigin() == null ) {
                result = Optional.of(BrainTreePaymentMethod.CREDITCARD);
            }else if (paymentMethodDetails.getOrigin().getType().equals(VISA_CHECKOUT)) {
                result = Optional.of(BrainTreePaymentMethod.VISACHECKOUTCARD);
            }else if (paymentMethodDetails.getOrigin().getType().equals(APPLE_PAY)) {
                result = Optional.of(BrainTreePaymentMethod.APPLEPAYCARD);
            }else if(paymentMethodDetails.getOrigin().getType().equals(GOOGLE_PAY)){
                result = Optional.of(BrainTreePaymentMethod.ANDROIDPAYCARD);
            }
        }
        return result;
    }

    public static String camelToSnake(String str) {
        return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase();
    }
}
