from datetime import date, datetime, timedelta

import mock
import pytest


def do_mock_backend(monkeypatch):

    class MockBackend(object):

        request = mock.Mock()

        description = {
            'parameters': [
                {
                    'name': 'capture_day',
                }
            ]
        }

    def get_backend(*args, **kwargs):
        def backend(*args, **kwargs):
            return MockBackend
        return backend

    import eopayment
    monkeypatch.setattr(eopayment, 'get_backend', get_backend)
    return MockBackend, eopayment.Payment('kind', None)


def test_deferred_payment(monkeypatch):
    mock_backend, payment = do_mock_backend(monkeypatch)

    capture_date = (datetime.now().date() + timedelta(days=3))
    payment.request(amount=12.2, capture_date=capture_date)
    mock_backend.request.assert_called_with(12.2, **{'capture_day': u'3'})

    # capture date can't be inferior to the transaction date
    capture_date = (datetime.now().date() - timedelta(days=3))
    with pytest.raises(
            ValueError, match='capture_date needs to be superior to the transaction date.'):
        payment.request(amount=12.2, capture_date=capture_date)

    # capture date should be a date object
    capture_date = 'not a date'
    with pytest.raises(ValueError, match='capture_date should be a datetime.date object.'):
        payment.request(amount=12.2, capture_date=capture_date)

    # using capture date on a backend that does not support it raise an error
    capture_date = (datetime.now().date() + timedelta(days=3))
    mock_backend.description['parameters'] = []
    with pytest.raises(ValueError, match='capture_date is not supported by the backend.'):
        payment.request(amount=12.2, capture_date=capture_date)


def test_paris_timezone(freezer, monkeypatch):
    freezer.move_to('2018-10-02 23:50:00')
    _, payment = do_mock_backend(monkeypatch)
    capture_date = date(year=2018, month=10, day=3)

    with pytest.raises(
            ValueError, match='capture_date needs to be superior to the transaction date'):
        # utcnow will return 2018-10-02 23:50:00,
        # converted to Europe/Paris it is already 2018-10-03
        # so 2018-10-03 for capture_date is invalid
        payment.request(amount=12.2, capture_date=capture_date)
