from django.test import TestCase

from web.forms import AppointmentAddForm
from web.forms import AppointmentEditForm
from web.models import Appointment, Worker, AppointmentTypeLink
from web.tests.functions import get_test_location, create_user, create_visit, create_location, create_appointment_type


class AppointmentEditFormTests(TestCase):
    def setUp(self):
        location = get_test_location()
        self.user = create_user()

        self.worker = Worker.get_by_user(self.user)
        self.worker.locations = [get_test_location()]
        self.worker.save()

        self.visit = create_visit()

        self.sample_data = {'first_name': 'name',
                            'length': '50',
                            'location': location.id,
                            'datetime_when': "2020-01-01",
                            }
        self.sample_data_with_status = self.sample_data
        self.sample_data_with_status['status'] = Appointment.APPOINTMENT_STATUS_NO_SHOW
        add_form = AppointmentAddForm(user=self.user, data=self.sample_data)
        add_form.instance.visit_id = self.visit.id
        self.appointment = add_form.save()
        self.appointment_type = create_appointment_type()

    def test_appointment_types_links_add_type(self):
        self.assertFalse(AppointmentTypeLink.objects.filter(appointment=self.appointment).all())
        sample_data = self.sample_data.copy()
        sample_data['appointment_types'] = [self.appointment_type.id]
        form = AppointmentEditForm(user=self.user, instance=self.appointment, data=sample_data)
        self.assertTrue(form.is_valid())
        form.save()
        self.assertEqual(1, AppointmentTypeLink.objects.filter(appointment=self.appointment).count(),
                         "one appointment link should have been created")

    def test_appointment_types_links_removed_after_date_changed(self):
        # create first link
        self.test_appointment_types_links_add_type()
        # modify link
        link = AppointmentTypeLink.objects.filter(appointment=self.appointment).first()
        self.assertIsNone(link.worker)
        link.worker = self.worker
        link.save()
        self.assertEqual(self.worker, link.worker)
        # change date
        sample_data = self.sample_data.copy()
        sample_data['appointment_types'] = [self.appointment_type.id]
        sample_data['datetime_when'] = '2021-01-01'
        form = AppointmentEditForm(user=self.user, instance=self.appointment, data=sample_data)
        self.assertTrue(form.is_valid())
        form.save()
        # check that the appointment links have been deleted and recreated
        links_count = AppointmentTypeLink.objects.filter(appointment=self.appointment).count()
        self.assertEqual(1, links_count,
                         "only one appointment link should exist, {} found".format(links_count))
        new_link = AppointmentTypeLink.objects.filter(appointment=self.appointment).first()
        self.assertNotEqual(link, new_link)
        self.assertIsNone(new_link.worker)

    def test_appointment_types_links_kept_if_no_date_changed(self):
        # create first link
        self.test_appointment_types_links_add_type()
        # modify link
        link = AppointmentTypeLink.objects.filter(appointment=self.appointment).first()
        self.assertIsNone(link.worker)
        link.worker = self.worker
        link.save()
        self.assertEqual(self.worker, link.worker)
        # change length
        sample_data = self.sample_data.copy()
        sample_data['length'] = '100'
        sample_data['appointment_types'] = [self.appointment_type.id]
        form = AppointmentEditForm(user=self.user, instance=self.appointment, data=sample_data)
        self.assertTrue(form.is_valid())
        self.appointment = form.save()
        self.assertEqual(100, self.appointment.length)
        # check that the appointment links have been kept
        links_count = AppointmentTypeLink.objects.filter(appointment=self.appointment).count()
        self.assertEqual(1, links_count,
                         "only one appointment link should exist, {} found".format(links_count))
        new_link = AppointmentTypeLink.objects.filter(appointment=self.appointment).first()
        self.assertEqual(link.id, new_link.id)
        self.assertEqual(self.worker, new_link.worker)

    def test_validation(self):
        form = AppointmentEditForm(user=self.user, data=self.sample_data_with_status)
        self.assertTrue(form.is_valid())

    def test_no_visit_field(self):
        form = AppointmentEditForm(user=self.user, data=self.sample_data_with_status)
        self.assertNotIn('visit', form.fields)

    def test_validation_invalid_location(self):
        self.sample_data['location'] = create_location(name="xxx").id
        form = AppointmentEditForm(user=self.user, data=self.sample_data_with_status)

        self.assertFalse(form.is_valid())
        self.assertTrue("location" in form.errors)