package com.braintree.graphql.commands.impl;

import com.braintree.commands.BrainTreeGetPaymentDetailsByNonce;
import com.braintree.commands.impl.AbstractCommand;
import com.braintree.hybris.data.graphql.commands.request.AuthenticationInsightInput;
import com.braintree.hybris.data.graphql.commands.response.BraintreePaymentMethodData;
import com.braintree.util.GenericBuilder;
import de.hybris.platform.payment.AdapterException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import static com.braintree.constants.BraintreeConstants.ID_PARAMETER;
import static com.braintree.constants.BraintreeConstants.RESULT_ERRORS;

public class DefaultBrainTreeGetPaymentDetailsByNonce extends AbstractCommand<String, BraintreePaymentMethodData>
        implements BrainTreeGetPaymentDetailsByNonce {

    private static final String DEFINITION_FILE_NAME = "getThreeDSDetailsByNonce";
    private static final String DATA = "data";
    private static final String NODE = "node";
    private static final String GETTING_PAYMENT_METHOD_ERROR_MESSAGE =
            "[BT get payment method] Error due getting payment method. ";
    private static final String INPUT = "input";

    @Override
    public BraintreePaymentMethodData perform(String nonce) {
        try {
            Map<String, Object> result = makeGraphQlCall(DEFINITION_FILE_NAME, createVariablesMap(nonce));
            ArrayList<Map<String, Object>> mapErrors = (ArrayList<Map<String, Object>>) result.get(RESULT_ERRORS);

            if (mapErrors == null) {

                return translateResponse((Map<String, Object>) result.get(DATA));

            } else {
                String message = GETTING_PAYMENT_METHOD_ERROR_MESSAGE + getFistErrorMessage(
                        mapErrors);
                throw new AdapterException(message);
            }
        } catch (Exception ex) {
            throw new AdapterException(ex.getMessage(), ex);
        }
    }

    private Map<String, Object> createVariablesMap(String nonce) {
        Map<String, Object> map = new HashMap<>();

        AuthenticationInsightInput input = GenericBuilder.of(AuthenticationInsightInput::new)
                .with(AuthenticationInsightInput::setMerchantAccountId,
                        getBrainTreeConfigService().getMerchantAccountIdForCurrentSiteAndCurrency())
                .build();

        map.put(ID_PARAMETER, nonce);
        map.put(INPUT, input);
        return map;
    }

    private BraintreePaymentMethodData translateResponse(Map<String, Object> data) {
        return objectMapper.convertValue(data.get(NODE), BraintreePaymentMethodData.class);
    }
}
