# -*- coding: UTF-8 -*-

from __future__ import absolute_import, unicode_literals
from django.db import IntegrityError, transaction
from rpc.decorators import bind_context
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException, GaiaRPCFaultException
from rpc.tool.dict_mixin import to_dict
from api.models import Person, Doctor, DoctorGroup, DoctorRelatedDoctorgroup, UserRelatedDoctorgroup, User
from hera.utils import model_edit
from hera.queries.asclelogin import DoctorGroupDQ
from doctor.models.person import DoctorStaffLogin

uri_pre = 'hera/asclelogin'

@bind_context(uri_pre + '/list')
def asclelogin_list(ctx, options):
    dtobj = DoctorGroupDQ()
    return dtobj.process(**options)

@bind_context(uri_pre + '/get')
def asclelogin_detail(ctx, asclelogin_id, options=None):
    try:
        doctorgroup = DoctorGroup.objects.get(id=asclelogin_id)
    except:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    doctorgroup_data = to_dict(doctorgroup, **options)
    doctorgroup_data['doctors'] = [doctor.id for doctor in doctorgroup.doctors()]
    person = [person.id for person in doctorgroup.users()]
    doctorgroup_data['users'] = [user.id for user in User.objects.filter(person__id__in=person)]
    return doctorgroup_data


@bind_context(uri_pre + '/modify')
@transaction.atomic
def asclelogin_edit(ctx, asclelogin_id=None, asclelogin_info=None):
    if asclelogin_info is None:
        return None
    doctors = asclelogin_info.pop('doctors')
    users = asclelogin_info.pop('users')
    ascleloginnews = model_edit(DoctorGroup, asclelogin_id, asclelogin_info)
    user_ids = set(users)

    new_doctors = set(Doctor.objects.filter(id__in=doctors))
    old_doctors = set(ascleloginnews.doctors())
    for doctor_obj in (new_doctors - old_doctors):
        DoctorRelatedDoctorgroup.objects.get_or_create(doctorgroup=ascleloginnews, doctor=doctor_obj)
    DoctorRelatedDoctorgroup.objects.filter(doctorgroup=ascleloginnews, doctor__in=(
        old_doctors - new_doctors)).delete()

    new_users = set(Person.objects.filter(user__id__in=users))
    old_users = set(ascleloginnews.users())
    for user_obj in (new_users - old_users):
        UserRelatedDoctorgroup.objects.get_or_create(doctorgroup=ascleloginnews, person=user_obj)
    UserRelatedDoctorgroup.objects.filter(doctorgroup=ascleloginnews, person__in=(
        old_users - new_users)).delete()

    old_user_ids = DoctorStaffLogin.objects.filter(can_login=True).values('person__user__id')
    old_user_set = set()
    for old_user_id in old_user_ids:
        old_user_set.add(old_user_id.get('person__user__id'))
    for user_id in user_ids - old_user_set:
        user = User.objects.get(id=user_id)
        DoctorStaffLogin.objects.get_or_create(person=user.person)
        try:
            Doctor.objects.get(user=user)
        except Doctor.DoesNotExist:
            Doctor.objects.create(user=user)
    can_logins = DoctorStaffLogin.objects.filter(person__user__id__in=user_ids)
    can_logins.update(can_login=True)
    for obj in can_logins:
        try:
            doctor, _ = Doctor.objects.get_or_create(user=obj.person.user)
            doctor.name = obj.person.user.last_name or obj.person.user.username
            doctor.save()
        except:
            raise
    if len(old_users - new_users) is not 0:
        if UserRelatedDoctorgroup.objects.filter(person__in=(old_users - new_users)).count() is 0:
            DoctorStaffLogin.objects.filter(person__in=(old_users - new_users)).update(can_login=False)
            Doctor.objects.filter(user__person__ascle_login__can_login=False, is_online=False).delete()

    return {'id': ascleloginnews.id}

