# vim: sw=4 ts=4 ft=perl

package WebService::Braintree::ClientApiHTTP;

use 5.010_001;
use strictures 1;

use HTTP::Request;
use URI::Escape;
use JSON;

use LWP::UserAgent;
use Moose;
use Carp qw(confess);
use DDP;

has 'config' => (is => 'ro', default => sub {WebService::Braintree->configuration });
has 'fingerprint' => (is => 'rw');
has 'shared_customer_identifier' => (is => 'rw');
has 'shared_customer_identifier_type' => (is => 'rw');

sub get_cards {
    my $self = shift;
    return _do_http($self, 'GET',
        $self->config->base_merchant_url .
        '/client_api/v1/payment_methods'.
        '?authorizationFingerprint=' . uri_escape($self->fingerprint) .
        '&sharedCustomerIdentifier=' . $self->shared_customer_identifier .
        '&sharedCustomerIdentifierType=' . $self->shared_customer_identifier_type,
    );
};

sub add_card {
    my ($self, $params) = @_;
    return _do_http($self, 'POST',
        $self->config->base_merchant_url . '/client_api/v1/payment_methods/credit_cards', $params,
    )
};

sub add_payment_method {
    my ($self, $params) = @_;
    $params->{'authorizationFingerprint'} = $self->fingerprint;
    $params->{'sharedCustomerIdentifier'} = $self->shared_customer_identifier;
    $params->{'sharedCustomerIdentifierType'} = $self->shared_customer_identifier_type;

    my $payment_method_type;
    if (defined($params->{'paypal_account'})) {
        $payment_method_type = 'paypal_accounts';
    } else {
        $payment_method_type = 'credit_cards';
    }

    return _do_http($self, 'POST',
        $self->config->base_merchant_url . '/client_api/v1/payment_methods/' . $payment_method_type,
        $params,
    );
}

sub get_one_time_nonce_for_paypal {
    my $self = shift;
    my $response = _do_http($self, 'POST',
        $self->config->base_merchant_url .
        '/client_api/v1/payment_methods/paypal_accounts.json' .
        '?authorization_fingerprint=' . uri_escape($self->fingerprint) .
        '&shared_customer_identifier=' . $self->shared_customer_identifier .
        '&shared_customer_identifier_type=' . $self->shared_customer_identifier_type .
        '&paypal_account[access_token]=access_token' .
        '&paypal_account[correlation_id]=1223' .
        '&paypal_account[options][validate]=false',
    );

    my $json = decode_json($response->content);
    my @paypalAccounts = @{$json->{'paypalAccounts'}};

    return $paypalAccounts[0]->{'nonce'};
}

sub get_future_payment_nonce_for_paypal {
    my $self = shift;
    my $response = _do_http($self, 'POST',
        $self->config->base_merchant_url .
        '/client_api/v1/payment_methods/paypal_accounts.json' .
        '?authorization_fingerprint=' . uri_escape($self->fingerprint) .
        '&shared_customer_identifier=' . $self->shared_customer_identifier .
        '&shared_customer_identifier_type=' . $self->shared_customer_identifier_type .
        '&paypal_account[consent_code]=consent' .
        '&paypal_account[correlation_id]=1223' .
        '&paypal_account[options][validate]=false',
    );

    my $json = decode_json($response->content);
    confess("Cannot create Future Payment Nonce:\n" . np($json)) unless $json->{paypalAccounts};
    return $json->{paypalAccounts}[0]{nonce};
}

sub get_nonce_for_new_card {
    my ($self, $credit_card_number) = @_;

    my $response = $self->add_card({
        share => 'true',
        credit_card => {
            number => $credit_card_number,
            expiration_date => '11/2099',
        }
    });

    return decode_json($response->content)->{'creditCards'}[0]{'nonce'};
}

sub get_nonce_for_new_card_with_params{
    my ($self, $params) = @_;
    my $response = $self->add_card({
        credit_card => $params,
    });

    return decode_json($response->content)->{'creditCards'}[0]{'nonce'};
}

sub create_paypal_account {
    my ($self, $params) = @_;
    my $updated_params = {
        authorization_fingerprint => $self->fingerprint,
        paypal_account => $params
    };

    _do_http($self, 'POST',
        $self->config->base_merchant_url . '/client_api/v1/payment_methods/paypal_accounts',
        $updated_params,
    );
}

sub _do_http {
    my ($self, $method, $url, $params) = @_;
    my $request = HTTP::Request->new($method => $url);

    $params->{authorization_fingerprint} = $self->fingerprint;
    $params->{shared_customer_identifier} = $self->shared_customer_identifier;
    $params->{shared_customer_identifier_type} = $self->shared_customer_identifier_type;
    # XXX This will always be true ... ?
    if ($params) {
        $request->content(encode_json $params);
        $request->content_type('application/json; charset=utf-8');
    }

    $request->header('X-ApiVersion' => $self->config->api_version);
    $request->header('environment' => $self->config->environment);
    $request->header('User-Agent' => 'Braintree Perl Module ' . WebService::Braintree->VERSION);

    my $agent = LWP::UserAgent->new;
    return $agent->request($request);
};

__PACKAGE__->meta->make_immutable;;

1;
__END__
