import csv
import traceback
from itertools import groupby
from optparse import make_option

from django.core.management.base import BaseCommand

from staff.person.models import Staff
from staff.departments.models import Department

from staff.person_filter.controller import FilterCtl
from staff.person_filter.saved_filter_ctl import SavedFilterCtl


def get_filter_id(rows):
    if is_department_filter(rows):
        return None

    filter_id = None
    filters = []
    operator = 'and'
    for row in rows:
        field_key = row['field'].lower()[:-6]
        field_key = 'group' if field_key == 'service' else field_key
        filters.append({
            'operator': operator,
            'field': row['field'],
            'condition': row['condition'],
            field_key: row['value'],
        })
        operator = 'or'

    filter_ctl = FilterCtl.get_by_data(data={'filters': filters})

    if filter_ctl.is_valid():
        filter_id = filter_ctl.create_id()
    else:
        raise Exception(filter_ctl.get_errors())

    return filter_id


def is_department_filter(rows):
    return (
        len(rows) == 1
        and rows[0]['field'] == 'DepartmentFilter'
        and rows[0]['condition'] == 'InHierarchy'
    )


def get_department_id(rows):
    if is_department_filter(rows):
        return int(rows[0]['value'])


def get_person_id(rows):
    if len(rows) == 1 and rows[0]['field'] == 'PersonFilter':
        return int(rows[0]['value'])


class Command(BaseCommand):
    option_list = BaseCommand.option_list + (
        make_option('--filepath', help='File path'),
    )

    def handle(self, *args, **options):
        filepath = options['filepath']
        persons = {p.id: p for p in Staff.objects.all()}
        departments = {p.id: p for p in Department.objects.all()}

        with open(filepath, 'r') as csvfile:
            reader = csv.DictReader(
                csvfile,
                delimiter=str(','),
                quotechar=str('"'),
                escapechar=str('\\')
            )

            def counter():
                n = 0
                while 1:
                    n -= 1
                    yield n
            counter = counter()

            def group_key(r):
                return (
                    next(counter)
                    if r['query_id'] == 'NULL'
                    else r['query_id']
                )

            for key, rows in groupby(reader, group_key):
                rows = list(rows)

                try:
                    saved_filter_data = {
                        'name': rows[0]['filter_name'].decode('utf-8'),
                        'absences_subscription': rows[0]['query_id'] == 'NULL',
                        'person': persons.get(get_person_id(rows)),
                        'department': departments.get(get_department_id(rows)),
                        'filter_id': get_filter_id(rows),
                    }

                    saved_filter_ctl = SavedFilterCtl(
                        persons[int(rows[0]['subscriber_id'])]
                    )
                    saved_filter_ctl.create(saved_filter_data, with_task=False)
                except Exception:
                    formatted_lines = traceback.format_exc().splitlines()
                    print(formatted_lines[-1])
                    print(rows, '\n')
