from odoo import api, fields, models
from odoo.exceptions import ValidationError
from .forte_request import ForteAPI
from json import dumps
import logging

_logger = logging.getLogger(__name__)


def forte_get_api(acquirer):
    return ForteAPI(acquirer.forte_organization_id,
                    acquirer.forte_access_id,
                    acquirer.forte_secure_key,
                    acquirer.environment)


class PaymentAcquirerForte(models.Model):
    _inherit = 'payment.acquirer'

    provider = fields.Selection(selection_add=[('forte', 'Forte')])
    forte_organization_id = fields.Char(string='Organization ID')
    forte_location_id = fields.Char(string='Location ID')  # Probably move to Journal...
    forte_access_id = fields.Char(string='Access ID')
    forte_secure_key = fields.Char(string='Secure Key')

    def _get_feature_support(self):
        """Get advanced feature support by provider.

        Each provider should add its technical in the corresponding
        key for the following features:
            * fees: support payment fees computations
            * authorize: support authorizing payment (separates
                         authorization and capture)
            * tokenize: support saving payment data in a payment.tokenize
                        object
        """
        res = super(PaymentAcquirerForte, self)._get_feature_support()
        res['authorize'].append('authorize')
        res['tokenize'].append('authorize')
        return res

    @api.multi
    def forte_test_credentials(self):
        self.ensure_one()
        api = forte_get_api(self)
        resp = api.test_authenticate()
        if not resp.ok:
            result = resp.json()
            if result and result.get('response'):
                raise ValidationError('Error: ' + dumps(result.get('response')))
        return True


class AccountPayment(models.Model):
    _inherit = 'account.payment'

    def _do_payment(self):
        self = self.with_context(payment_type=self.payment_type)
        return super(AccountPayment, self)._do_payment()


class TxForte(models.Model):
    _inherit = 'payment.transaction'

    def forte_s2s_do_transaction(self, **data):
        self.ensure_one()
        api = forte_get_api(self.acquirer_id)
        location = self.acquirer_id.forte_location_id
        amount = self.amount
        account_type = self.payment_token_id.forte_account_type
        routing_number = self.payment_token_id.forte_routing_number
        account_number = self.payment_token_id.forte_account_number
        account_holder = self.payment_token_id.forte_account_holder
        if not self.env.context.get('payment_type'):
            _logger.warn('Trying to do a payment with Forte and no contextual payment_type will result in an inbound transaction.')
        if self.env.context.get('payment_type', 'inbound') == 'inbound':
            resp = api.echeck_sale(location, amount, account_type, routing_number, account_number, account_holder)
        else:
            resp = api.echeck_credit(location, amount, account_type, routing_number, account_number, account_holder)

        if resp.ok and resp.json()['response']['response_desc'] == 'APPROVED':
            ref = resp.json()['response']['authorization_code']
            return self.write({'state': 'done', 'acquirer_reference': ref})
        else:
            result = resp.json()
            if result and result.get('response'):
                raise ValidationError('Error: ' + dumps(result.get('response')))

    def forte_s2s_do_refund(self, **data):
        self.ensure_one()
        api = forte_get_api(self.acquirer_id)
        location = self.acquirer_id.forte_location_id
        amount = self.amount
        account_type = self.payment_token_id.forte_account_type
        routing_number = self.payment_token_id.forte_routing_number
        account_number = self.payment_token_id.forte_account_number
        account_holder = self.payment_token_id.forte_account_holder
        if not self.env.context.get('payment_type'):
            _logger.warn('Trying to do a refund payment with Forte and no contextual payment_type will result in an inbound transaction refund.')
        if self.env.context.get('payment_type', 'inbound') == 'inbound':
            resp = api.echeck_credit(location, amount, account_type, routing_number, account_number, account_holder)
        else:
            resp = api.echeck_sale(location, amount, account_type, routing_number, account_number, account_holder)

        if resp.ok and resp.json()['response']['response_desc'] == 'APPROVED':
            ref = resp.json()['response']['authorization_code']
            return self.write({'state': 'refunded', 'acquirer_reference': ref})
        else:
            result = resp.json()
            if result and result.get('response'):
                raise ValidationError('Error: ' + dumps(result.get('response')))



class PaymentToken(models.Model):
    _inherit = 'payment.token'

    forte_account_type = fields.Char(string='Forte Account Type', help='e.g. Checking')
    forte_routing_number = fields.Char(string='Forte Routing Number', help='e.g. 021000021')
    forte_account_number = fields.Char(string='Forte Account Number', help='e.g. 000111222')
    forte_account_holder = fields.Char(string='Forte Account Holder', help='e.g. John Doe')
    # Boilerplate for views
    provider = fields.Selection(string='Provider', related='acquirer_id.provider')

    @api.model
    def forte_create(self, values):
        if values.get('forte_account_number'):
            #acquirer = self.env['payment.acquirer'].browse(values['acquirer_id'])
            #partner = self.env['res.partner'].browse(values['partner_id'])
            # eventually check the types and account numbers
            pass
        return values
