import datetime
import decimal
import os
import unittest
import requests_mock
from test.utils import assert_matching_tables

from parsons.etl.table import Table
from parsons.braintree.braintree import Braintree

_dir = os.path.dirname(__file__)


class TestBraintree(unittest.TestCase):

    def setUp(self):
        self.braintree = Braintree(merchant_id='abcd1234abcd1234', public_key='abcd1234abcd1234',
                                   private_key='abcd1234abcd1234abcd1234abcd1234')

    @requests_mock.Mocker()
    def test_dispute_search(self, m):
        m.post('https://api.braintreegateway.com:443'
               '/merchants/abcd1234abcd1234/disputes/advanced_search?page=1',
               text=open(f'{_dir}/test_data/dispute_example.xml').read())
        table = self.braintree.get_disputes(start_date="2020-01-01", end_date="2020-01-02")

        self.assertEqual(len(table.table), 3)
        self.assertEqual(table[0]['id'], 'abcd1234abcd1234')
        self.assertEqual(table[1]['id'], 'ghjk6789ghjk6789')
        self.assertEqual(table[0]['transaction_id'], 'd9f876fg')
        self.assertEqual(table[1]['transaction_id'], '98df87fg')
        self.assertEqual(table[0]['reason'], 'transaction_amount_differs')
        self.assertEqual(table[1]['reason'], 'fraud')

    @requests_mock.Mocker()
    def test_transaction_search(self, m):
        m.post('https://api.braintreegateway.com:443'
               '/merchants/abcd1234abcd1234/transactions/advanced_search_ids',
               text="""
               <search-results>
                  <page-size type="integer">50</page-size>
                  <ids type="array"><item>1234abcd</item> <item>0987asdf</item> </ids>
               </search-results>
        """)
        table = self.braintree.get_transactions(disbursement_start_date="2020-01-01",
                                                disbursement_end_date="2020-01-02",
                                                just_ids=True)
        assert_matching_tables(table, Table([['id'], ['1234abcd'], ['0987asdf']]))
        m.post('https://api.braintreegateway.com:443'
               '/merchants/abcd1234abcd1234/transactions/advanced_search',
               text=open(f'{_dir}/test_data/transaction_example.xml').read())
        full_table = self.braintree.get_transactions(disbursement_start_date="2020-01-01",
                                                     disbursement_end_date="2020-01-02",
                                                     table_of_ids=table)
        self.assertEqual(len(table.table), 3)
        self.assertEqual(len(full_table.table), 3)
        self.assertEqual(table[0]['id'], '1234abcd')
        self.assertEqual(table[1]['id'], '0987asdf')
        self.assertEqual(len(table[0].keys()), 1)
        self.assertEqual(len(full_table[0].keys()), 64)

        self.assertEqual(full_table[0]['disbursement_date'], datetime.date(2019, 12, 30))
        self.assertEqual(full_table[0]['credit_card_bin'], '789234')
        self.assertEqual(full_table[0]['disbursement_success'], True)
        self.assertEqual(full_table[0]['amount'], decimal.Decimal('150.00'))

    def test_query_generation(self):
        query = self.braintree._get_query_objects(
            'transaction', **{'disbursement_date': {'between': ["2020-01-01", "2020-01-01"]}})
        self.assertEqual(query[0].name, 'disbursement_date')
        self.assertEqual(query[0].to_param(), {'min': '2020-01-01', 'max': '2020-01-01'})

        query = self.braintree._get_query_objects(
            'transaction', **{'merchant_account_id': {'in_list': ["abc123"]}})

        self.assertEqual(query[0].name, 'merchant_account_id')
        self.assertEqual(query[0].to_param(), ['abc123'])

        query = self.braintree._get_query_objects(
            'dispute', **{
                'merchant_account_id': {'in_list': ["abc123"]},
                'effective_date': {'between': ["2020-01-01", "2020-01-01"]}})
        self.assertEqual(query[0].name, 'merchant_account_id')
        self.assertEqual(query[1].name, 'effective_date')
        self.assertEqual(query[1].to_param(), {'min': '2020-01-01', 'max': '2020-01-01'})
