#!/usr/bin/env perl
package TestFixtures;
use strict;
use warnings;

use Exporter;
use vars qw/ @ISA @EXPORT /;
@ISA = 'Exporter';
@EXPORT = qw/
    common_content
    inspect_response
    inspect_transaction
    make_api_request
/;

use Business::OnlinePayment;
use Data::Dumper;
use Test::More;

=head1 NAME

TestFixtures

=head1 DESCRIPTION

Common helper methods for all test units

=head1 BAMBORA DEVELOPER ACCOUNT

Do not use live credentials with these test units.  Bambora
provides no way to specifiy a test payment gateway.  They issue
test accounts instead.  See L<https://dev.na.bambora.com>

=head1 USAGE

    # set environment variables with credentials
    export BAMBORA_MERCHANT_ID=8675309
    export BAMBORA_API_KEY=XOXOXOXOXOXOXOX
    
    # run all tests
    prove -lv t
    
    # run a single test
    prove -lv t/031-payments-card-normal-authorizaiton.t

=head1 FUNCTIONS

=head2 common_content

A basic Business::OnlinePayment content hash, containing a
valid Bambora test card number, with Bambora's specified
correct billing address for their test cards

See L<https://dev.na.bambora.com/docs/references/payment_APIs/test_cards>

=cut

sub common_content {
    (
        #action         => 'Normal Authorization',

        amount         => '9.99',

        owner          => 'Business OnlinePayment',
        name           => 'Mitch Jackson',
        address        => '1407 Graymalkin Lane',
        city           => 'Vancouver',
        state          => 'BC',
        zip            => '111 111',
        country        => 'CA',

        invoice_number => time(),
        card_number    => '4030000010001234',
        cvv2           => '123',
        expiration     => '1122',
        phone          => '251-300-1300',
        email          => 'mitch@freeside.biz',
    )
}

=head2 inspect_response $response, \%expect, \@expect

Given $response, a decoded json api response, check the
response contains the keys/value defined in %expect, and
that response keys exist for keynames defined in @expect

=cut

sub inspect_response {
    no warnings 'uninitialized';

    my $response = shift;
    my $expect_href = shift || {};
    my $expect_aref = shift || [];

    die 'Expected $response hashref parameter'
        unless ref $response;

    for my $k ( keys %{$expect_href} ) {
        ok(
            $response->{$k} eq $expect_href->{$k},
            sprintf '$response->%s: %s eq %s',
                $k,
                $response->{$k},
                $expect_href->{$k}
        );
    }

    for my $k ( @{$expect_aref} ) {
        ok(
            defined $response->{$k},
            sprintf '$response->%s defined: %s',
                $k, $response->{$k}
        );
    }
}

=head2 inspect_transaction $transaction, \%expect, \@expect

Given a B::OP $tr, call methods defined as keys within %expect,
and validate the returned values match the values in %expect.
Check the methods defined in @expect return true values

=cut

sub inspect_transaction {
    no warnings 'uninitialized';
    my $tr = shift;
    my $expect_href = shift || {};
    my $expect_aref = shift || [];

    die 'Expected $tr B::OP transaction parameter'
        unless ref $tr;

    for my $k ( keys %{$expect_href} ) {
        ok(
            $tr->can($k) && $tr->$k() eq $expect_href->{$k},
            sprintf '$tr->%s: %s eq %s',
                $k,
                $tr->can($k) ? $tr->$k() : 'METHOD MISSING',
                $expect_href->{$k}
        );
    }

    for my $k ( @{$expect_aref} ) {
        ok(
            $tr->can($k) && defined $tr->$k(),
            sprintf '$tr->%s defined: %s',
                $k,
                $tr->can($k) ? $tr->$k() : 'METHOD MISSING',
        );
    } 
    
}

=head2 make_api_request \%content

Given a %content href, create a B::OP transaction and submit it

Returns the transaction object, and the decoded json response

=cut

sub make_api_request {
    my $content = shift;
    die 'expected href' unless ref $content;

  my $tr;
  ok( $tr = Business::OnlinePayment->new('Bambora'), 'Instantiatiate transaction' );
  ok( $tr->content( %$content ), 'Hand %content to transaction' );
  {
    local $@;
    eval { $tr->submit };
    ok( !$@, "Submit request to create Payment Profile, action: $content->{action}" );
    if ( $@ ) {
        warn Dumper({
            content => $content,
            error => $@,
        });
    }
  }

  my $response = $tr->response_decoded || {};

  return ( $tr, $response );
}

1;