# -*- coding: utf-8 -*-
# Generated by Django 1.11.24 on 2019-10-25 21:43
from __future__ import unicode_literals

from datetime import timedelta
from operator import itemgetter

from django.db import migrations, models
from django.db.migrations import RunPython

from river.models import APPROVED


def approval_key(approval):
    return "%s-%s-%s" % (approval.priority, approval.source_state.pk, approval.destination_state.pk)


sql = """
SELECT
    ta.id,
    ta.source_state_id,
    ta.destination_state_id,
    ta.transaction_date,
    ta.status,
    (
        select
            count(*)
        from river_transitionapproval ta_inner
        where ta_inner.workflow_id=ta.workflow_id AND
            ta_inner.object_id = ta.object_id AND
            ta_inner.source_state_id=ta.source_state_id AND
            ta_inner.destination_state_id=ta.destination_state_id AND
            ta_inner.priority=ta.priority AND
            ta_inner.date_created < ta.date_created
    ) as rw_number
FROM river_transitionapproval ta
WHERE rw_number=%d AND ta.workflow_id='%s' and ta.object_id='%s';
"""


def migrate_iteration(apps, schema_editor):
    def _iterate(workflow, initial_state, workflow_object, last_approved_iteration=-1, generation=0):
        with schema_editor.connection.cursor() as cursor:
            output = cursor.execute(sql % (generation, workflow.pk, workflow_obj.pk)).fetchall()
            if output:
                output = [
                    {
                        "pk": row[0],
                        "source_state_pk": row[1],
                        "destination_state_pk": row[2],
                        "approved_at": row[3],
                        "status": row[4]
                    }
                    for row in output
                ]

                last_approved = None
                approvals = list([approval for approval in output if approval["source_state_pk"] == initial_state.pk])
                iteration = last_approved_iteration + 1
                processed_source_states = set()
                while approvals:
                    workflow.transition_approvals.filter(pk__in=[approval['pk'] for approval in approvals]).update(iteration=iteration)
                    destination_state_pks = [approval['destination_state_pk'] for approval in approvals]
                    last_approved = next(reversed(sorted(filter(lambda a: a['status'] == APPROVED, approvals), key=itemgetter("approved_at"))), None)
                    processed_source_states.update([approval['source_state_pk'] for approval in approvals])
                    approvals = list([approval for approval in output if approval["source_state_pk"] in destination_state_pks and approval["source_state_pk"] not in processed_source_states])
                    iteration += 1

                if last_approved:
                    last_approved_object = workflow.transition_approvals.get(pk=last_approved["pk"])
                    _iterate(workflow, last_approved_object.destination_state, workflow_object, last_approved_object.iteration, generation + 1)

    Workflow = apps.get_model('river', 'Workflow')
    for workflow in Workflow.objects.all():
        model_class = apps.get_model(workflow.content_type.app_label, workflow.content_type.model)
        for workflow_obj in model_class.objects.all():
            _iterate(workflow, workflow.initial_state, workflow_obj)


class Migration(migrations.Migration):
    dependencies = [
        ('river', '0006_auto_20191020_1121'),
    ]

    operations = [
        migrations.AddField(
            model_name='transitionapproval',
            name='iteration',
            field=models.IntegerField(default=0, verbose_name='Priority'),
        ),
        migrations.RunPython(migrate_iteration, reverse_code=RunPython.noop),
    ]
