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

import io

from django.conf import settings
from django.db.models import Avg
from django.utils.translation import ugettext as _

from mtp.apps.common import xls
from mtp.apps.evaluations.models import Criterion, Evaluation, Exercise, Rating
from mtp.apps.trainings.models import GroupSet
from mtp.apps.workshops.models import Workshop


# TODO: Lots of string constants in here...

def export_workshop_stat_raw(trainer, session):

    training = session.training
    workshops = WorkshopProperties.objects.filter(
        user=trainer,
        workshop__training=training,
        is_deleted=False,
        hidden=False)
    for workshop in workshops:
        workshop.questions = WorkshopQuestion.objects.filter(
            workshop=workshop.workshop
        ).order_by('order')

    # INIT TAB THAT WILL STORE DATA
    global_stats = []
    per_workshop_stats = {}
    per_workshop_stats_raw = {}

    first_row_global = []
    first_row_global.append((_('first name'), "NAMES_HEADER_STYLE"))
    first_row_global.append((_('last name'), "NAMES_HEADER_STYLE"))
    for w in workshops:
        first_row_global.append((w.name, "PRIMARY_HEADER"))
        first_row_w = []
        first_row_raw_w = []
        second_row_raw_w = []

        first_row_w.append((_('first name'), "NAMES_HEADER_STYLE"))
        first_row_w.append((_('last name'), "NAMES_HEADER_STYLE"))

        first_row_raw_w.append("")
        first_row_raw_w.append("")
        second_row_raw_w.append((_('first name'), "NAMES_HEADER_STYLE"))
        second_row_raw_w.append((_('last name'), "NAMES_HEADER_STYLE"))

        for q in w.questions:
            first_row_w.append((q.title, "PRIMARY_HEADER"))
            first_row_raw_w.append((q.title, "PRIMARY_HEADER"))
            first = True
            if q.answers.filter(is_deleted=False).count() == 0:
                second_row_raw_w.append((q.title, "SECONDARY_HEADER"))
            else:
                for answer in q.answers.filter(is_deleted=False):
                    if first:
                        first = False
                    else:
                        first_row_raw_w.append(("", "EMPTY"))
                    if answer.good:
                        second_row_raw_w.append((answer.label, "TERTIARY_HEADER"))
                    else:
                        second_row_raw_w.append((answer.label, "SECONDARY_HEADER"))

        first_row_w.append((_('total'), "TERTIARY_HEADER"))
        per_workshop_stats[w.name] = []
        per_workshop_stats[w.name].append(first_row_w)
        per_workshop_stats_raw[w.name] = []
        per_workshop_stats_raw[w.name].append(first_row_raw_w)
        per_workshop_stats_raw[w.name].append(second_row_raw_w)

    first_row_global.append((_('total'), "TERTIARY_HEADER"))
    global_stats.append(first_row_global)

#    for user in session.users:
#        global_stats_u = []
#        per_workshop_stats_u = {}

    # PROCESS DATA EXTRACTION
    global_stats_d = {}
    per_workshop_stats_d = {}
    per_workshop_stats_raw_d = {}

    users = session.users.all()
    users_count = users.count()
    users_index = []
    for u in users:
        users_index.append(u)

    total_global = [0] * users_count

    for w in workshops:
        global_stats_d[w.name] = [0] * users_count
        per_workshop_stats_d[w.name] = {}
        per_workshop_stats_raw_d[w.name] = {}
        for q in w.questions:
            per_workshop_stats_d[w.name][q.title] = [0] * users_count
            per_workshop_stats_raw_d[w.name][q.title] = [None] * users_count
            answers = WorkshopQuestionUserAnswer.objects.filter(
                question=q,
                user__in=users).select_related(
                'answer',
                'user')
            for a in answers:
                if a.answer:
                    _index = users_index.index(a.user)
                    per_workshop_stats_d[w.name][q.title][_index] = a.answer.points
                    global_stats_d[
                        w.name][_index] = global_stats_d[
                        w.name][_index] + a.answer.points
                    total_global[_index] = total_global[_index] + a.answer.points
                    if not per_workshop_stats_raw_d[w.name][q.title][_index]:
                        per_workshop_stats_raw_d[w.name][q.title][_index] = []
                    per_workshop_stats_raw_d[w.name][q.title][_index].append(a.answer)
                else:
                    per_workshop_stats_raw_d[w.name][q.title][users_index.index(a.user)] = a.text

    # FILL TAB
    for index, u in enumerate(users):
        user_row_global = []
        user_row_global.append((u.first_name, "NAMES_HEADER_STYLE"))
        user_row_global.append((u.last_name, "NAMES_HEADER_STYLE"))
        for w in workshops:
            user_row_global.append((global_stats_d[w.name][index], "DEFAULT"))
            workshop_row = []
            workshop_row.append((u.first_name, "NAMES_STYLE"))
            workshop_row.append((u.last_name, "NAMES_STYLE"))
            for q in w.questions:
                workshop_row.append((per_workshop_stats_d[w.name][q.title][index], "DEFAULT"))
            workshop_row.append((global_stats_d[w.name][index], "DEFAULT"))
            per_workshop_stats[w.name].append(workshop_row)

            workshop_row_raw = []
            workshop_row_raw.append((u.first_name, "NAMES_STYLE"))
            workshop_row_raw.append((u.last_name, "NAMES_STYLE"))
            for q in w.questions:
                if q.answers.filter(is_deleted=False).count() == 0:
                    workshop_row_raw.append(
                        (per_workshop_stats_raw_d[
                            w.name][
                            q.title][index],
                            "DEFAULT"))
                else:
                    for answer in q.answers.filter(is_deleted=False):
                        if not per_workshop_stats_raw_d[w.name][q.title][index]:
                            workshop_row_raw.append(("", "DEFAULT"))
                        elif answer in per_workshop_stats_raw_d[w.name][q.title][index]:
                            workshop_row_raw.append(("X", "GOOD_ANSWER_STYLE"))
                        else:
                            workshop_row_raw.append(("", "DEFAULT"))
            per_workshop_stats_raw[w.name].append(workshop_row_raw)

        user_row_global.append((total_global[index], "DEFAULT"))
        global_stats.append(user_row_global)

    return global_stats, per_workshop_stats, per_workshop_stats_raw


def export_workshop_stat_xls(trainer, session):

    xls_file = io.BytesIO()
    xls_writer = xls.XLSWriter(xls_file)

    global_stats, per_workshop_stats, per_workshop_stats_raw = export_workshop_stat_raw(
        trainer, session)

    sheet_name = xls_writer.add_sheet('global')
    xls_writer.writerows(global_stats, sheet_name)

    workshops = WorkshopProperties.objects.filter(
        user=trainer,
        workshop__training=session.training,
        is_deleted=False,
        hidden=False)

    for __, workshop in enumerate(workshops):
        #    for w_name in per_workshop_stats.keys():

        w_name = workshop.name
        first_sheet_name = '%s' % (w_name)
        first_sheet_name = xls_writer.add_sheet(first_sheet_name)
        xls_writer.writerows(per_workshop_stats[w_name], first_sheet_name)
        second_sheet_name = 'verbatim - %s' % (w_name)
        second_sheet_name = xls_writer.add_sheet(second_sheet_name)
        xls_writer.writerows(per_workshop_stats_raw[w_name], second_sheet_name)

    xls_writer.save()

    return xls_file


def export_evaluation_stat_raw(trainer, session):
    training = session.training
    evaluations = EvaluationTypeProperties.objects.filter(
        user=trainer,
        evaluation_type__training=training,
        is_deleted=False,
        hidden=False)

    session_users = session.users.filter(
        is_deleted=False
    ).order_by(
        'last_name', 'first_name'
    )

    sheets = []
    for evaluation in evaluations:

        evaluator = GroupSet.mgroups.through.objects.filter(
            group_id=evaluation.evaluation_type.evaluators.id,
            groupset_id=training.default_group_set.id
        ).exists()

        auto_evaluator = GroupSet.mgroups.through.objects.filter(
            group_id=evaluation.evaluation_type.auto_evaluators.id,
            groupset_id=training.default_group_set.id
        ).exists()

        lines_auto = []
        lines_group = []
        exercice_name_line = [('', 'EMPTY'), ('', 'EMPTY')]
        criteria_name_line = [
            ('First name', 'NAMES_HEADER_STYLE'),
            ('Last name', 'NAMES_HEADER_STYLE')
        ]
        users_lines_auto = {}
        users_lines_group = {}
        average_line_auto = [('', 'EMPTY'), ('Average', 'TERTIARY_HEADER')]
        average_line_auto_count = [('', 'EMPTY'), ('Participation', 'TERTIARY_HEADER')]
        average_line_group = [('', 'EMPTY'), ('Average', 'TERTIARY_HEADER')]
        average_line_group_count = [('', 'EMPTY'), ('Participation', 'TERTIARY_HEADER')]

        for user in session_users:

            if evaluator:
                users_lines_group[user.username] = [
                    ('%s' % user.first_name, 'NAMES_STYLE'),
                    ('%s' % user.last_name, 'NAMES_STYLE')
                ]

            if auto_evaluator:
                users_lines_auto[user.username] = [
                    ('%s' % user.first_name, 'NAMES_STYLE'),
                    ('%s' % user.last_name, 'NAMES_STYLE')
                ]

            # 'pattern: pattern solid, fore_colour light_green; font: italic true, height 14'

        for exercice in evaluation.evaluation_type.evaluationexercice_set.filter(
                is_deleted=False).order_by('order'):

            exercice_name_line.append((exercice.label, 'PRIMARY_HEADER'))
            criteria_name_line.append(('', 'PRIMARY_HEADER'))
            average_line_auto.append(('', 'PRIMARY_HEADER'))
            average_line_auto_count.append(('', 'PRIMARY_HEADER'))
            average_line_group.append(('', 'PRIMARY_HEADER'))
            average_line_group_count.append(('', 'PRIMARY_HEADER'))

            for user in session_users:
                if evaluator:
                    users_lines_group[user.username].append(('', 'PRIMARY_HEADER'))
                if auto_evaluator:
                    users_lines_auto[user.username].append(('', 'PRIMARY_HEADER'))

            for num_crit in exercice.evaluationcriterianumeric_set.filter(is_deleted=False):
                exercice_name_line.append(('', 'EMPTY'))
                criteria_name_line.append((num_crit.description, 'SECONDARY_HEADER'))
                average_auto = 0
                average_auto_count = 0
                average_group = 0
                average_group_count = 0

                for user in session_users:
                    # auto eval
                    if auto_evaluator:
                        auto_value = EvaluationCriteriaNumericValue.objects.filter(
                            evaluation_criteria_numeric=num_crit,
                            jury=user,
                            candidate=user,
                            training_session=session
                        ).aggregate(
                            Avg('value')
                        )['value__avg']

                        if auto_value:
                            average_auto += auto_value
                            average_auto_count += 1

                        users_lines_auto[user.username].append((auto_value, 'DEFAULT'))

                    # group average
                    if evaluator:
                        group_value = EvaluationCriteriaNumericValue.objects.filter(
                            evaluation_criteria_numeric=num_crit,
                            candidate=user,
                            training_session=session
                        ).exclude(
                            jury=user
                        ).aggregate(
                            Avg('value')
                        )['value__avg']

                        if group_value:
                            average_group += group_value
                            average_group_count += 1

                        users_lines_group[user.username].append((group_value, 'DEFAULT'))

                if average_auto_count != 0:
                    average_auto = average_auto / average_auto_count

                if average_group_count != 0:
                    average_group = average_group / average_group_count

                average_line_auto.append((average_auto, 'DEFAULT'))
                average_line_auto_count.append((average_auto_count, 'DEFAULT'))

                average_line_group.append((average_group, 'DEFAULT'))
                average_line_group_count.append((average_group_count, 'DEFAULT'))

            for num_verb in exercice.evaluationcriteriaverbatim_set.filter(is_deleted=False):
                exercice_name_line.append(('', 'EMPTY'))
                criteria_name_line.append((num_verb.description, 'SECONDARY_HEADER'))
                for user in session_users:

                    if auto_evaluator:

                        auto_comments = ''
                        for comment in EvaluationCriteriaVerbatimValue.objects.filter(
                            jury=user,
                            candidate=user,
                            training_session=session,
                            evaluation_criteria_verbatim=num_verb,
                        ):
                            auto_comments = auto_comments + '\n+ ' + comment.value

                        users_lines_auto[user.username].append((auto_comments, 'DEFAULT'))

                    if evaluator:

                        group_comments = ''
                        for comment in EvaluationCriteriaVerbatimValue.objects.filter(
                            evaluation_criteria_verbatim=num_verb,
                            candidate=user,
                            training_session=session
                        ).exclude(
                            jury=user
                        ):
                            group_comments = group_comments + '\n+ ' + comment.value

                        users_lines_group[user.username].append((group_comments, 'DEFAULT'))

                average_line_auto.append(('', 'DEFAULT'))
                average_line_auto_count.append(('', 'DEFAULT'))
                average_line_group.append(('', 'DEFAULT'))
                average_line_group_count.append(('', 'DEFAULT'))

        if auto_evaluator:
            lines_auto.append(exercice_name_line)
            lines_auto.append(criteria_name_line)

            for user in session_users:
                lines_auto.append(users_lines_auto[user.username])

            lines_auto.append(average_line_auto)
            lines_auto.append(average_line_auto_count)
            evaluation_name = 'auto-%s' % (evaluation.name)
            sheets.append((evaluation_name, lines_auto))

        if evaluator:
            lines_group.append(exercice_name_line)
            lines_group.append(criteria_name_line)

            for user in session_users:
                lines_group.append(users_lines_group[user.username])

            lines_group.append(average_line_group)
            lines_group.append(average_line_group_count)
            evaluation_name = 'group-%s' % (evaluation.name)
            sheets.append((evaluation_name, lines_group))

    return sheets


def export_evaluation_stat_xls(trainer, session):
    sheets = export_evaluation_stat_raw(trainer, session)

    xls_file = io.BytesIO()
    xls_writer = xls.XLSWriter(xls_file, logo=settings.NORMAL_CLIENT_LOGO)

    for sheet_name, sheet_content in sheets:
        name = xls_writer.add_sheet(sheet_name)
        xls_writer.writerows(sheet_content, name)

    xls_writer.save()
    return xls_file
