import json
from datetime import timedelta
from decimal import Decimal

import pytest
from django.utils.timezone import now

from pretix.base.models import Event, Order, OrderRefund, Organizer, Team, User
from pretix.plugins.banktransfer.models import RefundExport
from pretix.plugins.banktransfer.views import (
    _row_key_func, _unite_transaction_rows,
)


@pytest.fixture
def env():
    o = Organizer.objects.create(name='Dummy', slug='dummy')
    event = Event.objects.create(
        organizer=o, name='Dummy', slug='dummy',
        date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'
    )
    user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
    t = Team.objects.create(organizer=event.organizer, can_view_orders=True, can_change_orders=True)
    t.members.add(user)
    t.limit_events.add(event)
    order = Order.objects.create(
        code='1Z3AS', event=event, email='admin@localhost',
        status=Order.STATUS_PAID,
        datetime=now(), expires=now() + timedelta(days=10),
        total=23
    )
    refund = OrderRefund.objects.create(
        order=order,
        amount=Decimal("23"),
        provider='banktransfer',
        state=OrderRefund.REFUND_STATE_CREATED,
        info=json.dumps({
            'payer': "Abc Def",
            'iban': "DE27520521540534534466",
            'bic': "HELADEF1MEG",
        })
    )
    return event, user, refund


url_prefixes = [
    "/control/event/dummy/dummy/",
    "/control/organizer/dummy/"
]


@pytest.mark.django_db
@pytest.mark.parametrize("url_prefix", url_prefixes)
def test_export_refunds_as_sepa_xml(client, env, url_prefix):
    client.login(email='dummy@dummy.dummy', password='dummy')
    r = client.post(f'{url_prefix}banktransfer/refunds/', {"unite_transactions": True}, follow=True)
    assert b"SEPA" in r.content
    r = client.get(f'{url_prefix}banktransfer/sepa-export/{RefundExport.objects.last().id}/')
    assert r.status_code == 200
    r = client.post(f'{url_prefix}banktransfer/sepa-export/{RefundExport.objects.last().id}/', {
        "account_holder": "Fission Festival",
        "iban": "DE71720690050653667120",
        "bic": "GENODEF1AIL",
    })
    assert "DE27520521540534534466" in "".join(str(part) for part in r.streaming_content)


@pytest.mark.django_db
@pytest.mark.parametrize("url_prefix", url_prefixes)
def test_export_refunds(client, env, url_prefix):
    client.login(email='dummy@dummy.dummy', password='dummy')
    r = client.get(f'{url_prefix}banktransfer/refunds/')
    assert r.status_code == 200
    r = client.post(f'{url_prefix}banktransfer/refunds/', {"unite_transactions": True}, follow=True)
    assert r.status_code == 200
    refund = RefundExport.objects.last()
    assert refund is not None
    assert b"Download CSV" in r.content
    r = client.get(f'{url_prefix}banktransfer/export/{refund.id}/')
    assert r.status_code == 200
    assert "DE27520521540534534466" in "".join(str(part) for part in r.streaming_content)


def test_unite_transaction_rows():
    rows = sorted([
        {
            'payer': "Abc Def",
            'iban': 'DE12345678901234567890',
            'bic': 'HARKE9000',
            'id': "ROLLA-R-1",
            'amount': Decimal("42.23"),
        },
        {
            'payer': "First Last",
            'iban': 'DE111111111111111111111',
            'bic': 'ikswez2020',
            'id': "PARTY-R-1",
            'amount': Decimal("6.50"),
        }
    ], key=_row_key_func)

    assert _unite_transaction_rows(rows) == rows

    rows = sorted(rows + [
        {
            'payer': "Abc Def",
            'iban': 'DE12345678901234567890',
            'bic': 'HARKE9000',
            'id': "ROLLA-R-1",
            'amount': Decimal("7.77"),
        },
        {
            'payer': "Another Last",
            'iban': 'DE111111111111111111111',
            'bic': 'ikswez2020',
            'id': "PARTY-R-2",
            'amount': Decimal("13.50"),
        }
    ], key=_row_key_func)

    assert _unite_transaction_rows(rows) == sorted([
        {
            'payer': "Abc Def",
            'iban': 'DE12345678901234567890',
            'bic': 'HARKE9000',
            'id': "ROLLA-R-1",
            'amount': Decimal("50.00"),
        },
        {
            'payer': 'Another Last, First Last',
            'iban': 'DE111111111111111111111',
            'bic': 'ikswez2020',
            'id': 'PARTY-R-1, PARTY-R-2',
            'amount': Decimal('20.00'),
        }], key=_row_key_func)

[((53, 1, 53, 52), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(53, 25, 53, 37): '"""url_prefix"""', (53, 39, 53, 51): 'url_prefixes'}, {}), "('url_prefix', url_prefixes)", False, 'import pytest\n'), ((69, 1, 69, 52), 'pytest.mark.parametrize', 'pytest.mark.parametrize', ({(69, 25, 69, 37): '"""url_prefix"""', (69, 39, 69, 51): 'url_prefixes'}, {}), "('url_prefix', url_prefixes)", False, 'import pytest\n'), ((17, 8, 17, 60), 'pretix.base.models.Organizer.objects.create', 'Organizer.objects.create', (), '', False, 'from pretix.base.models import Event, Order, OrderRefund, Organizer, Team, User\n'), ((22, 11, 22, 65), 'pretix.base.models.User.objects.create_user', 'User.objects.create_user', ({(22, 36, 22, 55): '"""dummy@dummy.dummy"""', (22, 57, 22, 64): '"""dummy"""'}, {}), "('dummy@dummy.dummy', 'dummy')", False, 'from pretix.base.models import Event, Order, OrderRefund, Organizer, Team, User\n'), ((23, 8, 23, 100), 'pretix.base.models.Team.objects.create', 'Team.objects.create', (), '', False, 'from pretix.base.models import Event, Order, OrderRefund, Organizer, Team, User\n'), ((76, 13, 76, 40), 'pretix.plugins.banktransfer.models.RefundExport.objects.last', 'RefundExport.objects.last', ({}, {}), '()', False, 'from pretix.plugins.banktransfer.models import RefundExport\n'), ((102, 11, 102, 40), 'pretix.plugins.banktransfer.views._unite_transaction_rows', '_unite_transaction_rows', ({(102, 35, 102, 39): 'rows'}, {}), '(rows)', False, 'from pretix.plugins.banktransfer.views import _row_key_func, _unite_transaction_rows\n'), ((121, 11, 121, 40), 'pretix.plugins.banktransfer.views._unite_transaction_rows', '_unite_transaction_rows', ({(121, 35, 121, 39): 'rows'}, {}), '(rows)', False, 'from pretix.plugins.banktransfer.views import _row_key_func, _unite_transaction_rows\n'), ((20, 18, 20, 23), 'django.utils.timezone.now', 'now', ({}, {}), '()', False, 'from django.utils.timezone import now\n'), ((29, 17, 29, 22), 'django.utils.timezone.now', 'now', ({}, {}), '()', False, 'from django.utils.timezone import now\n'), ((34, 15, 34, 28), 'decimal.Decimal', 'Decimal', ({(34, 23, 34, 27): '"""23"""'}, {}), "('23')", False, 'from decimal import Decimal\n'), ((37, 13, 41, 10), 'json.dumps', 'json.dumps', ({(37, 24, 41, 9): "{'payer': 'Abc Def', 'iban': 'DE27520521540534534466', 'bic': 'HELADEF1MEG'}"}, {}), "({'payer': 'Abc Def', 'iban': 'DE27520521540534534466', 'bic':\n    'HELADEF1MEG'})", False, 'import json\n'), ((29, 32, 29, 37), 'django.utils.timezone.now', 'now', ({}, {}), '()', False, 'from django.utils.timezone import now\n'), ((29, 40, 29, 58), 'datetime.timedelta', 'timedelta', (), '', False, 'from datetime import timedelta\n'), ((91, 22, 91, 38), 'decimal.Decimal', 'Decimal', ({(91, 30, 91, 37): '"""42.23"""'}, {}), "('42.23')", False, 'from decimal import Decimal\n'), ((98, 22, 98, 37), 'decimal.Decimal', 'Decimal', ({(98, 30, 98, 36): '"""6.50"""'}, {}), "('6.50')", False, 'from decimal import Decimal\n'), ((58, 59, 58, 86), 'pretix.plugins.banktransfer.models.RefundExport.objects.last', 'RefundExport.objects.last', ({}, {}), '()', False, 'from pretix.plugins.banktransfer.models import RefundExport\n'), ((60, 60, 60, 87), 'pretix.plugins.banktransfer.models.RefundExport.objects.last', 'RefundExport.objects.last', ({}, {}), '()', False, 'from pretix.plugins.banktransfer.models import RefundExport\n'), ((110, 22, 110, 37), 'decimal.Decimal', 'Decimal', ({(110, 30, 110, 36): '"""7.77"""'}, {}), "('7.77')", False, 'from decimal import Decimal\n'), ((117, 22, 117, 38), 'decimal.Decimal', 'Decimal', ({(117, 30, 117, 37): '"""13.50"""'}, {}), "('13.50')", False, 'from decimal import Decimal\n'), ((127, 22, 127, 38), 'decimal.Decimal', 'Decimal', ({(127, 30, 127, 37): '"""50.00"""'}, {}), "('50.00')", False, 'from decimal import Decimal\n'), ((134, 22, 134, 38), 'decimal.Decimal', 'Decimal', ({(134, 30, 134, 37): '"""20.00"""'}, {}), "('20.00')", False, 'from decimal import Decimal\n')]