# Generated by Django 3.1.6 on 2021-08-12 08:18

import common.db.encoder
from django.conf import settings
from django.db import migrations, models, transaction
import django.db.models.deletion
import uuid

from tickets.const import TicketType, TicketApprovalStrategy

ticket_assignee_m2m = list()


def get_ticket_assignee_m2m_info(apps, schema_editor):
    ticket_model = apps.get_model("tickets", "Ticket")
    for i in ticket_model.objects.only('id', 'assignees', 'action', 'created_by'):
        ticket_assignee_m2m.append((i.id, list(i.assignees.values_list('id', flat=True)), i.action, i.created_by))


def update_ticket_process_meta_state_status(apps, schema_editor):
    ticket_model = apps.get_model("tickets", "Ticket")
    updates = list()
    with transaction.atomic():
        for instance in ticket_model.objects.all():
            if instance.action == 'open':
                state = 'notified'
            elif instance.action == 'approve':
                state = 'approved'
            elif instance.action == 'reject':
                state = 'rejected'
            else:
                state = 'closed'
            instance.process_map = [{
                'state': state,
                'approval_level': 1,
                'approval_date': str(instance.date_updated),
                'processor': instance.processor.id if instance.processor else '',
                'processor_display': instance.processor_display if instance.processor_display else '',
                'assignees': list(instance.assignees.values_list('id', flat=True)) if instance.assignees else [],
                'assignees_display': instance.assignees_display if instance.assignees_display else []
            }, ]
            instance.state = state
            instance.meta['apply_assets'] = instance.meta.pop('approve_assets', [])
            instance.meta['apply_assets_display'] = instance.meta.pop('approve_assets_display', [])
            instance.meta['apply_actions'] = instance.meta.pop('approve_actions', 0)
            instance.meta['apply_actions_display'] = instance.meta.pop('approve_actions_display', [])
            instance.meta['apply_applications'] = instance.meta.pop('approve_applications', [])
            instance.meta['apply_applications_display'] = instance.meta.pop('approve_applications_display', [])
            instance.meta['apply_system_users'] = instance.meta.pop('approve_system_users', [])
            instance.meta['apply_system_users_display'] = instance.meta.pop('approve_system_users_display', [])
            updates.append(instance)
        ticket_model.objects.bulk_update(updates, ['process_map', 'state', 'meta', 'status'])


def create_step_and_assignee(apps, schema_editor):
    ticket_step_model = apps.get_model("tickets", "TicketStep")
    ticket_assignee_model = apps.get_model("tickets", "TicketAssignee")
    creates = list()
    with transaction.atomic():
        for ticket_id, assignees, action, created_by in ticket_assignee_m2m:
            if action == 'open':
                state = 'notified'
            elif action == 'approve':
                state = 'approved'
            else:
                state = 'rejected'
            step_instance = ticket_step_model.objects.create(ticket_id=ticket_id, state=state, created_by=created_by)
            for assignee_id in assignees:
                creates.append(
                    ticket_assignee_model(
                        step=step_instance, assignee_id=assignee_id, state=state, created_by=created_by
                    )
                )
        ticket_assignee_model.objects.bulk_create(creates)


def create_ticket_flow_and_approval_rule(apps, schema_editor):
    user_model = apps.get_model("users", "User")
    org_id = '00000000-0000-0000-0000-000000000000'
    ticket_flow_model = apps.get_model("tickets", "TicketFlow")
    approval_rule_model = apps.get_model("tickets", "ApprovalRule")
    super_user = user_model.objects.filter(role='Admin')
    assignees_display = ['{0.name}({0.username})'.format(i) for i in super_user]
    with transaction.atomic():
        for ticket_type in [TicketType.apply_asset, TicketType.apply_application]:
            ticket_flow_instance = ticket_flow_model.objects.create(created_by='System', type=ticket_type, org_id=org_id)
            approval_rule_instance = approval_rule_model.objects.create(strategy=TicketApprovalStrategy.super_admin, assignees_display=assignees_display)
            approval_rule_instance.assignees.set(list(super_user))
            ticket_flow_instance.rules.set([approval_rule_instance, ])


class Migration(migrations.Migration):
    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('tickets', '0009_auto_20210426_1720'),
    ]

    operations = [
        migrations.CreateModel(
            name='ApprovalRule',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
                ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
                ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
                ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
                ('level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1,
                                                   verbose_name='Approve level')),
                ('strategy', models.CharField(
                    choices=[('super_admin', 'Super admin'), ('org_admin', 'Org admin'), ('super_org_admin', 'Super admin and org admin'),
                             ('custom_user', 'Custom user')],
                    default='super_admin', max_length=64, verbose_name='Approve strategy')),
                ('assignees_display', models.JSONField(default=list, encoder=common.db.encoder.ModelJSONFieldEncoder,
                                                       verbose_name='Assignees display')),
                ('assignees',
                 models.ManyToManyField(related_name='assigned_ticket_flow_approval_rule', to=settings.AUTH_USER_MODEL,
                                        verbose_name='Assignees')),
            ],
            options={
                'verbose_name': 'Ticket flow approval rule',
            },
        ),
        migrations.RunPython(get_ticket_assignee_m2m_info),
        migrations.AddField(
            model_name='ticket',
            name='process_map',
            field=models.JSONField(default=list, encoder=common.db.encoder.ModelJSONFieldEncoder,
                                   verbose_name='Process'),
        ),
        migrations.AddField(
            model_name='ticket',
            name='state',
            field=models.CharField(
                choices=[('open', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'), ('closed', 'Closed')],
                default='open', max_length=16, verbose_name='State'),
        ),
        migrations.RunPython(update_ticket_process_meta_state_status),
        migrations.RemoveField(
            model_name='ticket',
            name='action',
        ),
        migrations.RemoveField(
            model_name='ticket',
            name='assignees',
        ),
        migrations.RemoveField(
            model_name='ticket',
            name='assignees_display',
        ),
        migrations.RemoveField(
            model_name='ticket',
            name='processor',
        ),
        migrations.RemoveField(
            model_name='ticket',
            name='processor_display',
        ),
        migrations.AddField(
            model_name='ticket',
            name='approval_step',
            field=models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1,
                                           verbose_name='Approval step'),
        ),
        migrations.CreateModel(
            name='TicketStep',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
                ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
                ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
                ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
                ('level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1,
                                                   verbose_name='Approve level')),
                ('state', models.CharField(
                    choices=[('notified', 'Notified'), ('approved', 'Approved'), ('rejected', 'Rejected')],
                    default='notified', max_length=64)),
                ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_steps',
                                             to='tickets.ticket', verbose_name='Ticket')),
            ],
            options={
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='TicketFlow',
            fields=[
                ('org_id',
                 models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
                ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
                ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
                ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
                ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
                ('type', models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm'),
                                                   ('apply_asset', 'Apply for asset'),
                                                   ('apply_application', 'Apply for application'),
                                                   ('login_asset_confirm', 'Login asset confirm'),
                                                   ('command_confirm', 'Command confirm')], default='general',
                                          max_length=64, verbose_name='Type')),
                ('approval_level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1,
                                                            verbose_name='Approve level')),
                ('rules', models.ManyToManyField(related_name='ticket_flows', to='tickets.ApprovalRule')),
            ],
            options={
                'verbose_name': 'Ticket flow',
            },
        ),
        migrations.CreateModel(
            name='TicketAssignee',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
                ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
                ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
                ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
                ('state', models.CharField(
                    choices=[('notified', 'Notified'), ('approved', 'Approved'), ('rejected', 'Rejected')],
                    default='notified', max_length=64)),
                ('assignee',
                 models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_assignees',
                                   to=settings.AUTH_USER_MODEL, verbose_name='Assignee')),
                ('step', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_assignees',
                                           to='tickets.ticketstep')),
            ],
            options={
                'verbose_name': 'Ticket assignee',
            },
        ),
        migrations.RunPython(create_step_and_assignee),
        migrations.RunPython(create_ticket_flow_and_approval_rule),
        migrations.AddField(
            model_name='ticket',
            name='flow',
            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets',
                                    to='tickets.ticketflow', verbose_name='TicketFlow'),
        ),
    ]
