import datetime
import logging

from django.urls import reverse

from web.tests.functions import create_subject, create_visit, create_appointment, create_worker, create_flying_team, \
    format_form_field
from web.forms import AppointmentEditForm, SubjectEditForm
from web.models import Appointment, Subject
from web.views.notifications import get_today_midnight_date
from web.tests import LoggedInTestCase

logger = logging.getLogger(__name__)


class AppointmentsViewTests(LoggedInTestCase):
    def setUp(self):
        super(AppointmentsViewTests, self).setUp()
        create_worker(self.user, True)

    def test_appointments_list_request(self):
        response = self.client.get(reverse('web.views.appointments'))
        self.assertEqual(response.status_code, 200)

    def test_appointments_edit(self):
        subject = create_subject()
        visit = create_visit(subject)
        appointment = create_appointment(visit, when=datetime.datetime.now())
        new_comment = 'new comment'
        new_status = appointment.APPOINTMENT_STATUS_NO_SHOW
        new_last_name = "new last name"
        form_appointment = AppointmentEditForm(user=self.user, instance=appointment, prefix="appointment")
        form_subject = SubjectEditForm(instance=subject, prefix="subject")
        form_data = {}
        for key, value in form_appointment.initial.items():
            if value is not None:
                form_data['appointment-{}'.format(key)] = value
        for key, value in form_subject.initial.items():
            if value is not None:
                form_data['subject-{}'.format(key)] = value
        form_data["appointment-comment"] = new_comment
        form_data["appointment-status"] = new_status
        form_data["subject-last_name"] = new_last_name
        response = self.client.post(
            reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)
        self.assertEqual(response.status_code, 302)
        updated_appointment = Appointment.objects.filter(id=appointment.id)[0]
        updated_subject = Subject.objects.filter(id=subject.id)[0]
        self.assertEqual(new_comment, updated_appointment.comment)
        self.assertEqual(new_status, updated_appointment.status)
        self.assertEqual(new_last_name, updated_subject.last_name)

    def test_appointments_edit_without_visit(self):
        appointment = create_appointment()
        appointment.visit = None
        appointment.save()

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

    def test_save_appointments_edit_without_visit(self):
        appointment = create_appointment()
        appointment.visit = None
        appointment.save()

        form_appointment = AppointmentEditForm(user=self.user, instance=appointment, prefix="appointment")
        form_data = {}
        for key, value in form_appointment.initial.items():
            if value is not None:
                form_data['appointment-{}'.format(key)] = value
        response = self.client.post(
            reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)

        self.assertEqual(response.status_code, 200)

    def test_save_as_finished_appointments_edit_without_visit(self):
        appointment = create_appointment(None, get_today_midnight_date())
        appointment.visit = None
        appointment.save()

        form_appointment = AppointmentEditForm(user=self.user, instance=appointment, prefix="appointment")
        form_data = {}
        for key, value in form_appointment.initial.items():
            if value is not None:
                form_data['appointment-{}'.format(key)] = format_form_field(value)
        form_data['appointment-status'] = Appointment.APPOINTMENT_STATUS_FINISHED
        self.client.post(reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)

        appointment_result = Appointment.objects.filter(id=appointment.id)[0]
        self.assertEqual(Appointment.APPOINTMENT_STATUS_FINISHED, appointment_result.status)

    def test_save_appointments_edit_with_invalid_nd_number(self):
        subject = create_subject()
        visit = create_visit(subject)
        appointment = create_appointment(visit, get_today_midnight_date())

        form_data = self.prepare_form(appointment, subject)
        form_data["appointment-status"] = Appointment.APPOINTMENT_STATUS_FINISHED

        response = self.client.post(
            reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)

        self.assertEqual(response.status_code, 200)

        updated_subject = Subject.objects.get(id=subject.id)
        self.assertFalse(updated_subject.information_sent)

    def test_save_appointments_edit_with_valid_nd_number(self):
        subject = create_subject()
        visit = create_visit(subject)
        appointment = create_appointment(visit, get_today_midnight_date())

        form_data = self.prepare_form(appointment, subject)
        form_data["appointment-status"] = Appointment.APPOINTMENT_STATUS_FINISHED
        form_data["subject-nd_number"] = "ND9999"

        response = self.client.post(
            reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)

        self.assertEqual(response.status_code, 302)

        updated_subject = Subject.objects.get(id=subject.id)
        self.assertTrue(updated_subject.information_sent)

    def prepare_form(self, appointment, subject):
        form_appointment = AppointmentEditForm(user=self.user, instance=appointment, prefix="appointment")
        form_subject = SubjectEditForm(instance=subject, prefix="subject")
        form_data = {}
        for key, value in form_appointment.initial.items():
            if value is not None:
                form_data['appointment-{}'.format(key)] = format_form_field(value)
        for key, value in form_subject.initial.items():
            if value is not None:
                form_data['subject-{}'.format(key)] = format_form_field(value)
        return form_data

    def test_subject_flying_team_location(self):
        subject = create_subject()
        visit = create_visit(subject)
        appointment = create_appointment(visit, get_today_midnight_date())

        form_data = self.prepare_form(appointment, subject)
        form_data["appointment-status"] = Appointment.APPOINTMENT_STATUS_FINISHED
        form_data["appointment-flying_team"] = create_flying_team().id
        form_data['appointment-status'] = Appointment.APPOINTMENT_STATUS_FINISHED
        form_data["subject-nd_number"] = "ND9999"

        self.client.post(reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)

        updated_subject = Subject.objects.get(id=subject.id)
        self.assertIsNotNone(updated_subject.flying_team)