from datetime import timedelta

from django.test import TestCase, RequestFactory
from django.http import HttpResponseRedirect
from django.contrib.auth.models import User

from payments.models import Payment
from payments.backends import CoinGateBackend


class CoinGateBackendTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user('test', 'test_user@example.com', None)

        self.backend_settings = dict(
            api_token='test',
            title='Test Title',
            currency='EUR',
        )

    def test_payment(self):
        payment = Payment.objects.create(
            user=self.user,
            time=timedelta(days=30),
            backend_id='coingate',
            amount=300
        )

        def fake_post(_backend, *, data={}):
            self.assertEqual(data['order_id'], '1')
            self.assertEqual(data['price_amount'], 3.0)
            self.assertEqual(data['price_currency'], 'EUR')
            self.assertEqual(data['receive_currency'], 'EUR')
            return {'id': 42, 'payment_url': 'http://testtoken/'}

        with self.settings(ROOT_URL='root'):
            backend = CoinGateBackend(self.backend_settings)
            backend._post = fake_post
            redirect = backend.new_payment(payment)

        self.assertIsInstance(redirect, HttpResponseRedirect)
        self.assertEqual(redirect.url, 'http://testtoken/')
        self.assertEqual(payment.backend_data.get('coingate_id'), 42)


        # Test a standard successful payment callback flow

        def post_callback(status):
            callback_data = {
                'token': payment.backend_data['coingate_token'],
                'order_id': str(payment.id),
                'status': status,
            }
            ipn_url = '/payments/callback/coingate/%d' % payment.id
            ipn_request = RequestFactory().post(
                ipn_url,
                data=callback_data)
            return backend.callback(payment, ipn_request)

        r = post_callback('pending')
        self.assertTrue(r)
        self.assertEqual(payment.status, 'new')

        r = post_callback('confirming')
        self.assertTrue(r)
        self.assertEqual(payment.status, 'new')

        r = post_callback('paid')
        self.assertTrue(r)
        self.assertEqual(payment.status, 'confirmed')
        self.assertEqual(payment.paid_amount, 300)

        time_left_s = self.user.vpnuser.time_left.total_seconds()
        self.assertAlmostEqual(time_left_s, payment.time.total_seconds(), delta=60)

