import os

import pytest
import vobject
from httmock import HTTMock, with_httmock

from passerelle.apps.holidays.models import Holidays

from .test_manager import login

pytestmark = pytest.mark.django_db

with open(os.path.join(os.path.dirname(__file__), 'data/holidays/Zone-A.ics')) as fd:
    RESPONSE_ZONE_A = fd.read()

with open(os.path.join(os.path.dirname(__file__), 'data/holidays/Zone-B.ics')) as fd:
    RESPONSE_ZONE_B = fd.read()


def ics_data(url, request):
    if url.path == '/openscol/fr-en-calendrier-scolaire/Zone-A.ics':
        return {'content': RESPONSE_ZONE_A, 'request': request, 'status_code': 200}
    if url.path == '/openscol/fr-en-calendrier-scolaire/Zone-B.ics':
        return {'content': RESPONSE_ZONE_B, 'request': request, 'status_code': 200}


@with_httmock(ics_data)
def test_holidays_ics(app):
    connector = Holidays.objects.create(slug='test', zone='a', holidays=[])

    resp = app.get('/holidays/test/holidays.ics')
    calendar = vobject.readOne(resp.text)
    assert not 'vevent' in calendar.contents

    connector.holidays.append('winter_holidays')
    connector.save()

    resp = app.get('/holidays/test/holidays.ics')
    calendar = vobject.readOne(resp.text)
    first_event = calendar.contents['vevent'][0]
    assert first_event.uid.value == 'winter_holidays-2018'
    assert first_event.summary.value == 'Vacances d’Hiver'
    assert first_event.categories.value == ['winter_holidays']
    assert str(first_event.dtstart.value) == '2018-02-10'
    assert str(first_event.dtend.value) == '2018-02-26'

    for i, event in enumerate(calendar.contents['vevent'][1:], start=2019):
        assert event.uid.value == 'winter_holidays-%s' % i
        assert event.summary.value == 'Vacances d’Hiver'
        assert event.categories.value == ['winter_holidays']

    connector.zone = 'b'
    connector.save()

    resp = app.get('/holidays/test/holidays.ics')
    calendar = vobject.readOne(resp.text)
    first_event = calendar.contents['vevent'][0]
    assert first_event.uid.value == 'winter_holidays-2018'
    assert str(first_event.dtstart.value) == '2018-02-24'
    assert str(first_event.dtend.value) == '2018-03-12'

    connector.holidays.append('summer_holidays')
    connector.save()

    resp = app.get('/holidays/test/holidays.ics')
    calendar = vobject.readOne(resp.text)
    assert calendar.contents['vevent'][0].uid.value == 'winter_holidays-2018'
    first_summer_event = next(x for x in calendar.contents['vevent'] if x.uid.value.startswith('summer'))
    assert first_summer_event.uid.value == 'summer_holidays-2018'
    assert first_summer_event.summary.value == 'Vacances d’Été'
    assert first_summer_event.categories.value == ['summer_holidays']
    assert str(first_summer_event.dtstart.value) == '2018-07-07'
    assert str(first_summer_event.dtend.value) == '2018-09-03'

    connector.holidays = [
        'winter_holidays',
        'spring_holidays',
        'summer_holidays',
        'all_saints_holidays',
        'christmas_holidays',
    ]
    connector.save()

    resp = app.get('/holidays/test/holidays.ics')
    calendar = vobject.readOne(resp.text)
    holiday_ids = {x.categories.value[0] for x in calendar.contents['vevent']}
    assert all(holiday_id in holiday_ids for holiday_id in connector.holidays)


def test_holidays_ics_invalid_responses(app):
    Holidays.objects.create(slug='test', zone='a', holidays=[])

    def server_error(url, request):
        return {'content': 'error', 'status_code': 500}

    with HTTMock(server_error):
        resp = app.get('/holidays/test/holidays.ics')
    assert resp.json['err'] == 1
    assert 'Error while getting ICS file' in resp.json['err_desc']

    def invalid_file(url, request):
        return {'content': 'invalid', 'status_code': 200}

    with HTTMock(invalid_file):
        resp = app.get('/holidays/test/holidays.ics')
    assert resp.json['err'] == 1
    assert 'Invalid ICS file' in resp.json['err_desc']

    def empty_file(url, request):
        return {
            'content': 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\nEND:VCALENDAR\r\n',
            'status_code': 200,
        }

    with HTTMock(empty_file):
        resp = app.get('/holidays/test/holidays.ics')
    assert resp.json['err'] == 1
    assert 'ICS file does not contain events' in resp.json['err_desc']


def test_holidays_manager(app, admin_user):
    login(app)

    resp = app.get('/manage/holidays/add')
    resp.form['title'] = 'Holidays'
    resp.form['slug'] = 'test'
    resp.form['description'] = 'test'
    resp.form['zone'] = 'c'
    resp.form['holidays'] = ['summer_holidays', 'christmas_holidays']

    resp = resp.form.submit().follow()
    assert 'Holidays: Vacances d’Été, Vacances de Noël' in resp.text
    assert 'Zone: C' in resp.text
