# -*- coding: utf-8 -*-

import logging

from django.utils.translation import ugettext_lazy as _

from events.common_app.utils import get_lang_with_fallback
from events.common_app.directory import CachedDirectoryClient
from events.surveyme_integration.variables.base import (
    BaseVariableCategory,
    BaseVariable,
    BaseRenderer,
)
from events.surveyme.answer_value import get_value_for_question


logger = logging.getLogger(__name__)


def get_org_id(uid):
    if not uid:
        return None
    fields = 'id,name,subscription_plan'
    client = CachedDirectoryClient()
    orgs = client.get_organizations(uid, fields=fields)
    if not orgs:
        return None
    return str(orgs[0]['id'])


def get_subscription_plan(uid):
    if not uid:
        return None
    fields = 'id,name,subscription_plan'
    client = CachedDirectoryClient()
    orgs = client.get_organizations(uid, fields=fields)
    if not orgs:
        return None
    return orgs[0]['subscription_plan']


def get_vip_status(dir_id):
    fields = 'id,name,subscription_plan,vip'
    client = CachedDirectoryClient()
    org = client.get_organization(dir_id, fields=fields)
    if not org:
        return None
    return org['vip']


def is_admin(uid, org_id=None, ):
    if not uid:
        return False
    org_id = org_id or get_org_id(uid)
    if not org_id:
        return False
    client = CachedDirectoryClient()
    user_info = client.get_user(org_id, uid, fields='is_admin')
    if not user_info:
        return None
    return bool(user_info.get('is_admin'))


def is_user(uid):
    return bool(get_org_id(uid))


def bool_to_string(value):
    return '1' if value else '0'


class DirectoryVariableCategory(BaseVariableCategory):
    name = 'directory'
    title = _('Директория')
    order = 9


class DirectoryBaseVariable(BaseVariable):
    @property
    def uid(self):
        user = self.answer.user
        if user:
            return user.uid


class DirectoryIsAdminVariable(DirectoryBaseVariable):
    name = 'directory.is_admin'
    title = _('Администратор?')
    category = DirectoryVariableCategory()

    def get_value(self, format_name=None):
        return bool_to_string(is_admin(self.uid))


class DirectoryIsUserVariable(DirectoryBaseVariable):
    name = 'directory.is_user'
    title = _('Состоит в Коннекте?')
    category = DirectoryVariableCategory()

    def get_value(self, format_name=None):
        return bool_to_string(is_user(self.uid))


class DirectoryOrgIdVariable(DirectoryBaseVariable):
    name = 'directory.org_id'
    title = _('Код организации')
    category = DirectoryVariableCategory()

    def get_value(self, format_name=None):
        return get_org_id(self.uid)


class DirectorySubscriptionPlanVariable(DirectoryBaseVariable):
    name = 'directory.subscription_plan'
    title = _('Платность')
    category = DirectoryVariableCategory()

    def get_value(self, format_name=None):
        return get_subscription_plan(self.uid)


class DirectoryVIPVariable(DirectoryBaseVariable):
    name = 'directory.vip'
    title = _('Статус VIP')
    category = DirectoryVariableCategory()
    arguments = ['question']
    filters = {'question': {'answer_type': 'answer_short_text', }}

    def __init__(self, question, **kwargs):
        super(DirectoryVIPVariable, self).__init__(**kwargs)
        self.question = question

    def get_value(self, format_name=None):
        domain = get_value_for_question(self.answer, self.question)
        is_vip = 'Not defined'
        if domain:
            client = CachedDirectoryClient()
            org = client.who_is(domain=domain)
            if org:
                vip = get_vip_status(str(org['org_id']))
                if vip is not None:
                    is_vip = bool(vip)
        return is_vip


class DirectoryStaffVariableCategory(BaseVariableCategory):
    name = 'dir_staff'
    title = _('Данные организации')
    order = 10


class DirectoryStaffBaseVariableRenderer(BaseRenderer, BaseVariable):
    def __init__(self, question=None, **kwargs):
        super().__init__(**kwargs)
        self.question = question

    def get_value(self, format_name=None):
        result = self.get_response(self.field)
        return self.parse_result(result)

    def get_response(self, field):
        user_uid = self.get_user_uid()
        org_id = self.get_org_id()
        if user_uid and org_id:
            fields = 'name,birthday,contacts,email,groups,groups.name,groups.type,department'
            client = CachedDirectoryClient()
            response = client.get_user(org_id, user_uid, fields=fields)
            if response:
                return self.get_field_value(field.split('.'), response)

    def parse_result(self, result):
        return result

    def get_user_uid(self):
        if self.question:
            data = self.answer.as_dict().get(self.question, {})
            if data and data.get('question', {}).get('options', {}).get('data_source') == 'dir_user':
                value = data.get('value', [])
                if isinstance(value, list) and len(value) > 0:
                    return value[0].get('key')
        else:
            return str(self.answer.user.uid)

    def get_org_id(self):
        org = self.answer.survey.org
        if org:
            return org.dir_id

    def get_field_value(self, field_path, response, index=0):
        value = response.get(field_path[index], '')
        index += 1
        if len(field_path) == index:
            return value
        response = value or {}
        return self.get_field_value(field_path, response, index)


class DirectoryStaffLanguageMixin(object):
    default_lang = 'ru'

    def parse_result(self, result):
        if isinstance(result, dict):
            lang, fallback_lang = get_lang_with_fallback()
            if lang in result:
                result = result[lang]
            elif fallback_lang in result:
                result = result[fallback_lang]
            elif self.default_lang in result:
                result = result[self.default_lang]
        return result


class DirectoryStaffBirthDateVariableRenderer(DirectoryStaffBaseVariableRenderer):
    format_name = 'dir_staff.birth_day'
    format_title = _('Дата рождения')
    field = 'birthday'


class DirectoryStaffFirstNameVariableRenderer(DirectoryStaffLanguageMixin, DirectoryStaffBaseVariableRenderer):
    format_name = 'dir_staff.first_name'
    format_title = _('Имя')
    field = 'name.first'


class DirectoryStaffLastNameVariableRenderer(DirectoryStaffLanguageMixin, DirectoryStaffBaseVariableRenderer):
    format_name = 'dir_staff.last_name'
    format_title = _('Фамилия')
    field = 'name.last'


class DirectoryStaffMiddleNameVariableRenderer(DirectoryStaffLanguageMixin, DirectoryStaffBaseVariableRenderer):
    format_name = 'dir_staff.middle_name'
    format_title = _('Отчество')
    field = 'name.middle'


class DirectoryStaffContactsVariableRenderer(DirectoryStaffBaseVariableRenderer):
    format_name = None
    format_title = None
    field = 'contacts'
    field_type = None

    def parse_result(self, result):
        if isinstance(result, list):
            result = ', '.join(
                item.get('value')
                for item in result
                if item.get('type') == self.field_type and item.get('value')
            )
        return result


class DirectoryStaffPhoneVariableRenderer(DirectoryStaffContactsVariableRenderer):
    format_name = 'dir_staff.phone'
    format_title = _('Телефон')
    field_type = 'phone'


class DirectoryStaffEmailVariableRenderer(DirectoryStaffContactsVariableRenderer):
    format_name = 'dir_staff.email'
    format_title = _('Почта')
    field_type = 'email'


class DirectoryStaffGroupsVariableRenderer(DirectoryStaffLanguageMixin, DirectoryStaffBaseVariableRenderer):
    format_name = 'dir_staff.groups'
    format_title = _('Команды')
    field = 'groups'

    def parse_result(self, result):
        if isinstance(result, list):
            result = ', '.join(
                super(DirectoryStaffGroupsVariableRenderer, self).parse_result(item.get('name'))
                for item in result
                if item.get('type') == 'generic'
            )
        return result


class DirectoryStaffDepartmentVariableRenderer(DirectoryStaffLanguageMixin, DirectoryStaffBaseVariableRenderer):
    format_name = 'dir_staff.department'
    format_title = _('Подразделение')
    field = 'department.name'


class DirectoryStaffManagerVariableRenderer(DirectoryStaffLanguageMixin, DirectoryStaffBaseVariableRenderer):
    format_name = 'dir_staff.manager'
    format_title = _('Руководитель')
    field = 'department.id'
    sub_fields = ('head.name.first', 'head.name.last')

    def get_response(self, field):
        department_id = super().get_response(field)
        if department_id:
            client = CachedDirectoryClient()
            fields = 'id,head.name'
            response = client.get_department(self.get_org_id(), department_id, fields=fields)
            if response:
                response = [
                    self.get_field_value(sub_field.split('.'), dict(response))
                    for sub_field in self.sub_fields
                ]
                return response

    def parse_result(self, response):
        if isinstance(response, list):
            response = ' '.join(
                super(DirectoryStaffManagerVariableRenderer, self).parse_result(item)
                for item in response
            ).strip()
        else:
            response = super(DirectoryStaffManagerVariableRenderer, self).parse_result(response)
        return response


class DirectoryStaffBaseVariable(BaseVariable):
    category = DirectoryStaffVariableCategory()
    if_bulk = True
    connect_only = True


class DirectoryStaffMetaUserVariable(DirectoryStaffBaseVariable):
    name = 'dir_staff.meta_user'
    title = _('Инфо о пользователе')
    arguments = []

    renderer_classes = [
        DirectoryStaffFirstNameVariableRenderer,
        DirectoryStaffLastNameVariableRenderer,
        DirectoryStaffMiddleNameVariableRenderer,
        DirectoryStaffBirthDateVariableRenderer,
        DirectoryStaffPhoneVariableRenderer,
        DirectoryStaffEmailVariableRenderer,
        DirectoryStaffGroupsVariableRenderer,
        DirectoryStaffDepartmentVariableRenderer,
        DirectoryStaffManagerVariableRenderer,
    ]

    def __init__(self, question=None, **kwargs):
        super().__init__(**kwargs)
        self.kwargs = kwargs
        self.question = question

    def get_value(self, format_name=None):
        render_variable_instance = self.get_renderer_variable_instance(format_name=format_name)
        return render_variable_instance.get_value()

    def get_renderer_variable_instance(self, format_name):
        renderer_class = self.get_renderer_class(format_name=format_name) or self.renderer_classes[0]
        return renderer_class(question=self.question, **self.kwargs)


class DirectoryStaffMetaQuestionVariable(DirectoryStaffMetaUserVariable):
    name = 'dir_staff.meta_question'
    title = _('Инфо из ответа на вопрос')
    filters = {'question': {'param_data_source': 'dir_user', }}
    arguments = ['question', ]
