# -*- coding: utf-8 -*-
from collections import namedtuple, defaultdict, deque
from django.conf import settings
from events.surveyme.models import ProfileSurveyAnswer


AnswerType = namedtuple('AnswerType', [
    'id',  # int
    'slug',  # str
    'is_group',  # bool
])

AnswerOptions = namedtuple('AnswerOptions', [
    'required',  # bool
    'data_source',  # str
    'multiple',  # bool
    'ordering',  # str
    'date_range',  # bool
    'account_id',  # str
])

Question = namedtuple('Question', [
    'id',  # int
    'slug',  # str
    'answer_type',  # AnswerType
    'options',  # AnswerOptions
])

ChoiceValue = namedtuple('ChoiceValue', [
    'key',  # str
    'text',  # str
])

TitleValue = namedtuple('TitleValue', [
    'row',  # ChoiceValue
    'col',  # ChoiceValue
])

DateRangeValue = namedtuple('DateRangeValue', [
    'begin',  # str
    'end',  # str
])

FileValue = namedtuple('FileValue', [
    'name',  # str
    'path',  # str
    'size',  # int
])

AnswerQuestion = namedtuple('AnswerQuestion', [
    'question',  # Question
    'value',  # str|bool|int|DateRangeValue|List[ChoiceValue]|List[TitleValue]|List[FileValue]|List[List[AnswerQuestion]]
])

Answer = namedtuple('Answer', [
    'id',  # int
    'created',  # datetime
    'data',  # List[AnswerQuestion]
])


def _create_choice_value(data):
    return ChoiceValue(
        key=data.get('key'),
        text=data.get('text'),
    )


def _create_title_value(data):
    return TitleValue(
        row=_create_choice_value(data.get('row')),
        col=_create_choice_value(data.get('col')),
    )


def _create_date_value(data):
    return data


def _create_date_range_value(data):
    return DateRangeValue(
        begin=data.get('begin'),
        end=data.get('end'),
    )


def _create_file_value(data):
    return FileValue(
        name=data.get('name'),
        path=data.get('path'),
        size=data.get('size'),
    )


def _create_value(question, data):
    value = data
    if question.answer_type.slug == 'answer_choices':
        if question.options.data_source != 'survey_question_matrix_choice':
            value = [
                _create_choice_value(it)
                for it in data or []
            ]
        else:
            value = [
                _create_title_value(it)
                for it in data or []
            ]
    elif question.answer_type.slug == 'answer_date':
        if question.options.date_range:
            value = _create_date_range_value(data)
        else:
            value = _create_date_value(data)
    elif question.answer_type.slug == 'answer_files':
        value = [
            _create_file_value(it)
            for it in data or []
        ]
    elif question.answer_type.slug == 'answer_group':
        value = [
            [
                _create_answer_question(it)
                for it in fieldset
            ]
            for fieldset in data or []
        ]
    return value


def _create_answer_type(data):
    pk = data.get('id')
    slug = data.get('slug')
    is_group = slug == 'answer_group'
    return AnswerType(id=pk, slug=slug, is_group=is_group)


def _create_answer_options(data):
    return AnswerOptions(
        required=bool(data.get('required')),
        data_source=data.get('data_source'),
        multiple=bool(data.get('multiple')),
        ordering=data.get('ordering'),
        date_range=bool(data.get('date_range')),
        account_id=data.get('account_id'),
    )


def _create_question(data):
    return Question(
        id=data.get('id'),
        slug=data.get('slug'),
        options=_create_answer_options(data.get('options', {})),
        answer_type=_create_answer_type(data.get('answer_type')),
    )


def _create_answer_question(data):
    question = _create_question(data.get('question'))
    value = _create_value(question, data.get('value'))
    return AnswerQuestion(question=question, value=value)


def create_answer_data(data):
    data = data or {}
    return [
        _create_answer_question(it)
        for it in data.get('data', [])
    ]


def create_answer_object(pk, created, data):
    return Answer(id=pk, created=created, data=create_answer_data(data))


def fetch_answer_data(data):
    answer_data = deque(data.get('data') or [])
    while answer_data:
        answer_question = answer_data.popleft()
        if not answer_question:
            continue
        answer_type_slug = answer_question.get('question', {}).get('answer_type', {}).get('slug')
        if answer_type_slug == 'answer_group':
            for group_items in answer_question.get('value') or []:
                if isinstance(group_items, dict):
                    group_items = group_items.values()
                if group_items:
                    answer_data.extend(group_items)
        yield answer_question


def get_answer(answer_id):
    pk, created, data = (
        ProfileSurveyAnswer.objects.using(settings.DATABASE_ROLOCAL)
        .values_list(
            'pk',
            'date_created',
            'data',
        )
        .get(pk=answer_id)
    )
    return create_answer_object(pk, created, data)


def get_last_answer(survey_id, user_id=None):
    answer_qs = (
        ProfileSurveyAnswer.objects.using(settings.DATABASE_ROLOCAL)
        .filter(
            survey_id=survey_id,
        )
    )
    if user_id:
        answer_qs = answer_qs.filter(user_id=user_id)
    args = (
        answer_qs.values_list(
            'pk',
            'date_created',
            'data',
        )
        .order_by()
        .last()
    )
    if args:
        return create_answer_object(*args)


def as_dict(answer):
    result = {}
    for it in answer.data:
        if it.question.answer_type.is_group:
            children = defaultdict(list)
            for fieldset in it.value:
                for child in fieldset:
                    children[child.question.id].append(child.value)
            result.update(children)
        else:
            result[it.question.id] = it.value
    return result
