# coding: utf-8
from __future__ import unicode_literals

import json
import yenv
from collections import OrderedDict
from itertools import chain
from optparse import make_option

from django.conf import settings

from staff.emission.django.emission_master.models import MasterLog
from staff.groups.models import Group
from staff.lib import requests
from staff.lib.db import atomic

from django.core.management.base import BaseCommand


if yenv == 'production':
    staff_api_groups_url = 'https://staff-api.yandex-team.ru/v3/groups?_fields=id&_limit=999999'
else:
    staff_api_groups_url = 'https://staff-api.test.yandex-team.ru/v3/groups?_fields=id&_limit=999999'


class Command(BaseCommand):
    help = 'Удаляет повторяющиеся пересохранения групп из логов emission_masterlog'
    option_list = BaseCommand.option_list + (
        make_option(
            '--last_id',
            action='store',
            dest='last_processed_id',
            # default=0,
            help='id последней обработанной записи из emission_masterlog',
        ),
    )

    def handle(self, *args, **options):
        last_processed_id = options.get('last_processed_id')
        fix(last_processed_id)


def get_from_api(group_ids=None):
    params = {}
    if isinstance(group_ids, list):
        params = {'id': ','.join([str(pk) for pk in group_ids])}
    api_result = requests.post(
        staff_api_groups_url,
        data=params,
        headers={'Authorization': 'OAuth {}'.format(settings.ROBOT_STAFF_OAUTH_TOKEN)},
    ).json()['result']

    return [group['id'] for group in api_result]


def get_log_records(last_id):
    log_qs = (
        MasterLog.objects
        .filter(id__gte=last_id)
        .order_by('id')
        .values_list('id', 'data', 'action')
    )

    records = (
        (json.loads(data)[0], log_id, action)
        for log_id, data, action in log_qs.values_list('id', 'data', 'action')
    )

    records = (
        (data['pk'], log_id, action)
        for data, log_id, action in records
        if data['model'] == 'django_intranet_stuff.group'
    )

    return records


def group_and_filter_deleted_records(records):
    deleted = set()
    grouped = OrderedDict()
    for group_id, log_id, action in records:
        if group_id in deleted:
            continue

        if action == 'delete':
            deleted.add(group_id)
            if group_id in grouped:
                del grouped[group_id]
            continue

        if group_id not in grouped:
            grouped[group_id] = [log_id]
        else:
            grouped[group_id].append(log_id)

    return grouped


def filter_by_api(records):
    groups_ids_from_api = get_from_api(records.keys())
    for group_id in records.keys():
        if group_id not in groups_ids_from_api:
            del records[group_id]
    return records


def delete_logs(log_ids):
    MasterLog.objects.filter(id__in=log_ids).delete()
    print('Log clear')


def resave_groups(group_ids):
    groups = {
        group.id: group
        for group in Group.objects.filter(id__in=group_ids).select_for_update()
    }

    for num, group_id in enumerate(group_ids, start=1):
        groups[group_id].save()
        print(groups[group_id].id)
        if not num % 100:
            print('Re-saved %d' % num)


@atomic
def fix(last_id):
    records = get_log_records(last_id)
    records = group_and_filter_deleted_records(records)
    records = filter_by_api(records)

    group_ids = records.keys()
    log_ids = chain.from_iterable(records.values())

    resave_groups(group_ids)
    delete_logs(log_ids)

    print('Done.')
