# -*- coding: utf-8 -*-
from bson.objectid import ObjectId
from collections import defaultdict
from django.conf import settings
from rest_framework import serializers

from events.startrek.fields import STARTREK_FIELDS
from events.surveyme_integration.services.base.context_processors.base import ContextProcessorBase
from events.surveyme_integration.services.base.context_processors.fields import (
    AttachmentFromQuestionSerializer,
    RenderedCharField,
    RenderedFieldMixin,
    RenderedJSONField,
)
from events.surveyme_integration.filters import LoginFilter
from events.surveyme_integration.utils import get_variables_keys
from events.surveyme_integration.variables.staff import StaffHrPartnerVariableRenderer
from events.surveyme_integration.variables.form import (
    FormQuestionAnswerChoicesIdsVariable,
    FormQuestionAnswerChoiceSlugVariable,
)


ALLOWED_SPLIT = {
    FormQuestionAnswerChoicesIdsVariable.name,
    FormQuestionAnswerChoiceSlugVariable.name,
}

ALLOWED_RENDERER_SPLIT = {
    StaffHrPartnerVariableRenderer.format_name,
}

ALLOWED_SPLIT_TRACKER_FIELDS = {
    'components',
    'tags',
    'yandexApplications',
    'yandexService',
    'employment',
    'emailProvider',
    'smartphoneExperience',
    'webSearchOnDesktop',
    'webSearchOnSmartphone',
    'defaultBrowser',
    'browserOnSmartphone',
    'transportApplications',
    'stationNew',
    '6130e15a5c54a3159ed74545--puteshestviabilety',
    '6130e15a5c54a3159ed74545--puteshestvia',
    '6130e15a5c54a3159ed74545--puteshestviazhilye',
    '6130e15a5c54a3159ed74545--markaSmartfona',
    '6130e15a5c54a3159ed74545--platformaSmartfona',
}


class StartrekUniqueField(serializers.CharField):
    def get_range(self):
        if settings.IS_BUSINESS_SITE:
            return 0
        elif settings.APP_TYPE == 'forms_int':
            return 1
        return 2

    def to_representation(self, value):
        range_id = self.get_range()
        notification_id = super().to_representation(value)
        unique = f'FORMS/{range_id}/{notification_id}'

        if settings.STARTREK_UNIQUE_IN_TESTS:
            unique = f'{unique}/{ObjectId()}'

        return unique


class StartrekFieldsSerializer(RenderedFieldMixin, serializers.Serializer):
    def to_representation(self, value, additional_data=None):
        value = value or []
        additional_data = additional_data or {}
        fields = {}
        for field in value:
            field_key = field.get('key') or {}
            native_name = field_key.get('id') or field_key.get('slug')
            native_type = field_key['type']
            additional_data['field_type'] = native_type
            native_value = super(StartrekFieldsSerializer, self).to_representation(field.get('value'), additional_data)
            if not self.is_need_to_skip(field, native_value):
                native_value = self.process_output(native_value, native_name, native_type, field.get('value'))
                if native_type.startswith('array'):
                    if native_name not in fields:
                        fields[native_name] = []
                    fields[native_name].extend(native_value)
                else:
                    fields[native_name] = native_value
        return fields

    def split_value(self, value):
        result = []
        for part in value.split(','):
            v = part.strip()
            if v:
                result.append(v)
        return result

    def process_output(self, native_value, native_name, native_type, value):
        if isinstance(native_value, str):
            variable_keys = get_variables_keys(value)
            if native_type == 'user':
                native_value = LoginFilter().apply_filter(native_value)
            elif native_type == 'array/user':
                native_value = LoginFilter().split_value(native_value)
            elif native_type == 'array/board' or native_name in ALLOWED_SPLIT_TRACKER_FIELDS:
                native_value = self.split_value(native_value)
            elif 'array' in native_type and len(variable_keys) == 1:
                obj_with_variables = self.get_variables_source()
                variable_key = variable_keys.pop()
                variables = obj_with_variables.variables_map
                var = variables.get(variable_key)
                if var and (var.var in ALLOWED_SPLIT or var.format_name in ALLOWED_RENDERER_SPLIT):
                    native_value = self.split_value(native_value)

            field = STARTREK_FIELDS.get(native_type)
            if field:
                native_value = field.get(native_name, native_value)

        return native_value

    def process_data(self, data):
        variable_data = defaultdict(list)
        data = super(StartrekFieldsSerializer, self).process_data(data)

        native_type = data['field_type']
        if 'user' in native_type:
            variable_data['filters'].append('login')
        return variable_data

    def is_need_to_skip(self, field, native_value):
        return self.is_none_value(native_value)


class StartrekUserField(RenderedCharField):
    def as_string(self, value, additional_data):
        login_filter = LoginFilter()
        rendered_value = super().as_string(value, additional_data)
        return login_filter.apply_filter(rendered_value or '')


class StartrekArrayUserField(RenderedJSONField):
    def as_string(self, value, additional_data):
        login_filter = LoginFilter()
        rendered_value = super().as_string(value, additional_data)
        return login_filter.apply_filter(rendered_value or '')


class StartrekContextProcessor(ContextProcessorBase):
    queue = serializers.CharField(source='subscription.startrek.queue')
    parent = serializers.CharField(source='subscription.startrek.parent')
    author = StartrekUserField(source='subscription.startrek.author')
    assignee = StartrekUserField(source='subscription.startrek.assignee')
    summary = RenderedCharField(source='subscription.title')
    description = RenderedCharField(source='subscription.body')
    type = serializers.CharField(source='subscription.startrek.type')
    priority = serializers.CharField(source='subscription.startrek.priority')
    tags = RenderedJSONField(source='subscription.startrek.tags')
    followers = StartrekArrayUserField(source='subscription.startrek.followers')
    unique = StartrekUniqueField(source='notification_unique_id')
    attachments = AttachmentFromQuestionSerializer(
        source='answer.survey.surveyquestion_set.filter_by_answer_type_with_files',
        selective_source='subscription.questions.filter_by_answer_type_with_files',
    )
    yandexuid = serializers.CharField(source='answer.user.uid')
    cloud_uid = serializers.CharField(source='answer.user.cloud_uid')
    fields = StartrekFieldsSerializer(source='subscription.startrek.fields')

    class Meta(ContextProcessorBase.Meta):
        fields = ContextProcessorBase.Meta.fields + [
            'queue',
            'parent',
            'author',
            'assignee',
            'summary',
            'description',
            'type',
            'priority',
            'tags',
            'followers',
            'unique',
            'attachments',
            'yandexuid',
            'cloud_uid',
            'fields',
        ]
