import datetime
import logging
import os

from django.contrib.auth.models import User

from web.models import Location, AppointmentType, StudySubject, Worker, Visit, Appointment, ConfigurationItem, \
    Language, ContactAttempt, FlyingTeam, Availability, Subject, Study, StudyColumns, StudyNotificationParameters, \
    VoucherType, VoucherTypePrice, Voucher
from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, REDCAP_BASE_URL_CONFIGURATION_TYPE, \
    SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, CONTACT_TYPES_PHONE, \
    MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID, VOUCHER_STATUS_NEW
from web.redcap_connector import RedcapSubject
from web.views.notifications import get_today_midnight_date

logger = logging.getLogger(__name__)


def create_get_suffix(params):
    result = "?"
    for key in params:
        result += key + "=" + str(params[key]) + "&"
    return result


def create_location(name="test"):
    return Location.objects.create(name=name)


def create_voucher_type():
    return VoucherType.objects.create(code="X", study=get_test_study())


def create_voucher_type_price():
    return VoucherTypePrice.objects.create(voucher_type=create_voucher_type(),
                                           price=12.34,
                                           start_date=get_today_midnight_date(),
                                           end_date=get_today_midnight_date())


def create_empty_study_columns():
    study_columns = StudyColumns.objects.create(
        postponed=False,
        datetime_contact_reminder=False,
        type=False,
        default_location=False,
        flying_team=False,
        screening_number=False,
        nd_number=False,
        mpower_id=False,
        comments=False,
        referral=False,
        diagnosis=False,
        year_of_diagnosis=False,
        information_sent=False,
        pd_in_family=False,
        resigned=False,
        resign_reason=False,
    )

    return study_columns


def create_study(name="test"):
    study_columns = StudyColumns.objects.create()
    notification_parameters = StudyNotificationParameters.objects.create()
    return Study.objects.create(name=name, columns=study_columns, notification_parameters=notification_parameters)


def create_voucher(study_subject=None):
    if study_subject is None:
        study_subject = create_study_subject()
    return Voucher.objects.create(number="123456",
                                  study_subject=study_subject,
                                  issue_date=get_today_midnight_date(),
                                  expiry_date=get_today_midnight_date(),
                                  voucher_type=create_voucher_type(),
                                  status=VOUCHER_STATUS_NEW)


def create_empty_notification_parameters():
    return StudyNotificationParameters.objects.create(
        exceeded_visits_visible=False,
        unfinished_visits_visible=False,
        approaching_visits_without_appointments_visible=False,
        unfinished_appointments_visible=False,
        visits_with_missing_appointments_visible=False,
        subject_no_visits_visible=False,
        approaching_visits_for_mail_contact_visible=False,
        subject_require_contact_visible=False,
        missing_redcap_subject_visible=False,
        inconsistent_redcap_subject_visible=False,
    )


def create_empty_study(name="test"):
    study_columns = create_empty_study_columns()
    notification_parameters = create_empty_notification_parameters()
    result = create_study(name)
    result.columns = study_columns
    result.notification_parameters = notification_parameters
    result.save()
    return result


def get_test_location():
    locations = Location.objects.filter(name="test")
    if len(locations) > 0:
        return locations[0]
    else:
        return create_location()


def get_test_study():
    studies = Study.objects.filter(name="test-study")
    if len(studies) > 0:
        return studies[0]
    else:
        return create_study("test-study")


def create_appointment_type():
    return AppointmentType.objects.create(
        code="C",
        default_duration="10",
        description="test",
    )


def create_contact_attempt(subject=None, worker=None):
    if subject is None:
        subject = create_study_subject()
    if worker is None:
        worker = create_worker()

    return ContactAttempt.objects.create(subject=subject,
                                         worker=worker,
                                         type=CONTACT_TYPES_PHONE,
                                         datetime_when=get_today_midnight_date(),
                                         success=True,
                                         comment="Successful contact attempt",
                                         )


def create_subject():
    return Subject.objects.create(
        first_name="Piotr",
        last_name="Gawron",
        sex=SEX_CHOICES_MALE,
        country_id=COUNTRY_AFGHANISTAN_ID
    )


def create_study_subject(subject_id=1, subject=None):
    if subject is None:
        subject = create_subject()
    return StudySubject.objects.create(
        default_location=get_test_location(),
        type=SUBJECT_TYPE_CHOICES_CONTROL,
        screening_number="piotr's number" + str(subject_id),
        study=get_test_study(),
        subject=subject
    )


def create_red_cap_subject():
    result = RedcapSubject()
    result.nd_number = "123"
    return result


def create_user(username=None, password=None):
    if username is None:
        username = 'piotr'
    if password is None:
        password = 'top_secret'
    user = User.objects.create_user(
        username=username,
        email='jacob@bla',
        password=password)

    create_worker(user)
    return user


def create_worker(user=None, with_test_location=False):
    worker = Worker.objects.create(
        first_name='piotr',
        last_name="gawron",
        email='jacob@bla',
        user=user,
    )
    if with_test_location:
        worker.locations = [get_test_location()]
        worker.save()
    return worker


def create_availability(worker=None):
    if worker is None:
        worker = create_worker()
    availability = Availability.objects.create(person=worker,
                                               day_number=MONDAY_AS_DAY_OF_WEEK,
                                               available_from=get_today_midnight_date(),
                                               available_till=get_today_midnight_date(),
                                               )
    return availability


def create_visit(subject=None):
    if subject is None:
        subject = create_study_subject()
    return Visit.objects.create(datetime_begin=get_today_midnight_date() + datetime.timedelta(days=-31),
                                datetime_end=get_today_midnight_date() + datetime.timedelta(days=31),
                                subject=subject,
                                is_finished=False)


def create_appointment(visit=None, when=None):
    if visit is None:
        visit = create_visit()
    # if when is None:
    #     when = get_today_midnight_date()
    return Appointment.objects.create(
        visit=visit,
        length=30,
        location=get_test_location(),
        status=Appointment.APPOINTMENT_STATUS_SCHEDULED,
        datetime_when=when)


def create_configuration_item():
    item = ConfigurationItem.objects.create()
    item.type = "TEST"
    item.value = "xxx"
    item.name = "yyy"
    item.save()
    return item


def create_flying_team(place=None):
    if place is None:
        place = "CHEM "
    result = FlyingTeam.objects.create(place=place)
    return result


def create_language(name="French", locale="fr_FR"):
    language = Language(name=name, locale=locale)
    language.save()
    return language


def get_resource_path(filename):
    return os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', filename)


def format_form_field(value):
    if isinstance(value, datetime.date):
        return value.strftime('%Y-%m-%d')
    elif isinstance(value, datetime.datetime):
        return value.strftime('%Y-%m-%d %H:%M')
    elif value is None:
        return ""
    else:
        return value


def prepare_test_redcap_connection():
    Language.objects.create(name="Finnish").save()
    Language.objects.create(name="Italian").save()
    token_item = ConfigurationItem.objects.filter(type=REDCAP_TOKEN_CONFIGURATION_TYPE)[0]
    # noinspection SpellCheckingInspection
    token_item.value = "5C75EEC3DBDDA5218B6ACC0424B3F695"
    token_item.save()
    url_item = ConfigurationItem.objects.filter(type=REDCAP_BASE_URL_CONFIGURATION_TYPE)[0]
    url_item.value = "https://luxparktest.org/redcap/"
    url_item.save()