import datetime
import logging

from django.urls import reverse

from web.forms import VisitDetailForm, VisitAddForm
from web.models import Visit, MailTemplate
from web.models.constants import MAIL_TEMPLATE_CONTEXT_VISIT
from web.tests import LoggedInTestCase
from web.tests.functions import create_study_subject, create_visit, create_appointment, create_appointment_type, \
    create_language, get_resource_path
from web.views.notifications import get_today_midnight_date

logger = logging.getLogger(__name__)


class VisitViewTests(LoggedInTestCase):
    def test_visit_details_request(self):
        visit = create_visit()
        create_appointment(visit)
        visit.subject.subject.address = "SUBJECT_ADDRESS_DATA"
        visit.subject.subject.save()
        visit.subject.comments = "STUDY_SUBJECT_COMMENTS_DATA"
        visit.subject.save()

        response = self.client.get(reverse('web.views.visit_details', kwargs={'id': visit.id}))
        self.assertEqual(response.status_code, 200)
        self.assertTrue(visit.subject.comments in response.content, msg="No study subject data in rendered response")
        self.assertTrue(visit.subject.subject.address in response.content, msg="No subject data in rendered response")

    def test_save_visit_details(self):
        visit = create_visit()
        create_appointment(visit)

        form_data = self.create_visit_detail_form_data(visit)

        response = self.client.post(reverse('web.views.visit_details', kwargs={'id': visit.id}), data=form_data)
        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, "error")

    @staticmethod
    def create_visit_detail_form_data(visit):
        visit_detail_form = VisitDetailForm(instance=visit)
        form_data = {}
        for key, value in visit_detail_form.initial.items():
            if value is not None:
                if isinstance(value, datetime.datetime):
                    form_data[key] = value.strftime("%Y-%m-%d")
                else:
                    form_data[key] = value
        return form_data

    def test_render_visit_details_with_mail_templates(self):
        language = create_language(name="German")
        template_name = "german_template"
        template_file = get_resource_path('upcoming_appointment_FR.docx')
        visit = create_visit()
        visit.subject.subject.default_written_communication_language = language
        visit.subject.subject.save()

        MailTemplate(name=template_name, language=language, context=MAIL_TEMPLATE_CONTEXT_VISIT,
                     template_file=template_file).save()

        form_data = self.create_visit_detail_form_data(visit)

        response = self.client.post(reverse('web.views.visit_details', kwargs={'id': visit.id}), data=form_data)
        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, "error")
        self.assertTrue(template_name in response.content)

    def test_render_add_visit(self):
        study_subject = create_study_subject()

        response = self.client.get(reverse('web.views.visit_add', kwargs={'subject_id': study_subject.id}))
        self.assertEqual(response.status_code, 200)

    def test_save_add_visit(self):
        visit_count = Visit.objects.all().count()
        subject = create_study_subject()

        form = VisitAddForm()
        form_data = {}
        for key, value in form.initial.items():
            if value is not None:
                if isinstance(value, datetime.datetime):
                    form_data[key] = value.strftime("%Y-%m-%d")
                else:
                    form_data[key] = value

        form_data["datetime_begin"] = "2017-01-01"
        form_data["datetime_end"] = "2017-04-01"
        form_data["subject"] = subject.id

        response = self.client.post(reverse('web.views.visit_add', kwargs={'subject_id': subject.id}), data=form_data)
        self.assertEqual(response.status_code, 302)
        self.assertFalse("error" in response.content)

        visit_count_new = Visit.objects.all().count()

        self.assertEqual(visit_count + 1, visit_count_new)

    def test_mark_as_finished(self):
        visit = create_visit()

        self.assertFalse(visit.is_finished)

        response = self.client.get(reverse('web.views.visit_mark', args=[visit.id, "finished"]))
        self.assertEqual(response.status_code, 302)

        new_visit = Visit.objects.get(id=visit.id)
        self.assertTrue(new_visit.is_finished)

    def test_visit_list(self):
        create_visit()

        response = self.client.get(reverse('web.views.visits'))
        self.assertEqual(response.status_code, 200)

    def test_visit_with_missing_appointment_list(self):
        visit = create_visit()
        visit.appointment_types.add(create_appointment_type())
        visit.save()

        response = self.client.get(reverse('web.views.visits_with_missing_appointments'))
        self.assertEqual(response.status_code, 200)

    def test_approaching_visits_without_appointments(self):
        visit = create_visit()
        visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=2)
        visit.save()

        response = self.client.get(reverse("web.views.approaching_visits_without_appointments"))
        self.assertEqual(response.status_code, 200)

    def test_approaching_visits_for_mail_contact(self):
        visit = create_visit()
        visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=100)
        visit.save()

        response = self.client.get(reverse("web.views.approaching_visits_for_mail_contact"))
        self.assertEqual(response.status_code, 200)

    def test_exceeded_visits(self):
        visit = create_visit()
        visit.datetime_end = "2011-01-01"
        visit.save()

        response = self.client.get(reverse("web.views.exceeded_visits"))
        self.assertEqual(response.status_code, 200)

    def test_unfinished_visits(self):
        visit = create_visit()
        visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=-10)
        visit.save()
        response = self.client.get(reverse("web.views.unfinished_visits"))
        self.assertEqual(response.status_code, 200)