# Generated by Django 2.2.2 on 2019-06-11 09:37

from django.core.exceptions import ObjectDoesNotExist
from django.db import migrations


def migrate_service(RoleObjectPermission, RoleContentType, permissions, service):
    # First, rename the VIEW_USERS and APPROVER roles to DEPUTY and MANAGER
    service.roles.filter(name="VIEW_USERS").update(name="DEPUTY")
    service.roles.filter(name="APPROVER").update(name="MANAGER")
    user_role = service.roles.get(name="USER")
    deputy_role = service.roles.get(name="DEPUTY")
    manager_role = service.roles.get(name="MANAGER")
    # VIEW_USERS was able to view users with the USER role
    # DEPUTY also needs to be able to send messages and approve requests for the USER role
    for permission in permissions:
        deputy_role.object_permissions.get_or_create(
            permission=permission, content_type=RoleContentType, object_pk=user_role.pk
        )
    # APPROVER was able to send messages and approve requests for the USER role
    # We want to add the ability to view users for the USER role along with the
    # ability to view users, send messages and approve requests for the DEPUTY role
    for permission in permissions:
        manager_role.object_permissions.get_or_create(
            permission=permission, content_type=RoleContentType, object_pk=user_role.pk
        )
        manager_role.object_permissions.get_or_create(
            permission=permission,
            content_type=RoleContentType,
            object_pk=deputy_role.pk,
        )
    # If the user had VIEW_USERS but not APPROVER, migrate their VIEW_USERS grant
    # If the user had VIEW_USERS and APPROVER, delete their VIEW_USERS grant
    for grant in deputy_role.grants.all():
        if manager_role.grants.filter(access__user=grant.user).exists():
            grant.delete()
        else:
            grant.access.role = manager_role
            grant.save()
    for request in deputy_role.requests.all():
        if manager_role.requests.filter(access__user=request.user).exists():
            request.delete()
        else:
            request.access.role = manager_role
            request.save()


def migrate(apps, schema_editor):
    """
    Forward migration that modifies the previous VIEW_USERS and APPROVER roles
    to become DEPUTY and MANAGER with appropriate permissions, and shuffles
    the grants around accordingly.

    We don't provide a backward migration as the operations cannot be fully undone
    without storing extra information.
    """
    Service = apps.get_model("jasmin_services", "Service")
    Role = apps.get_model("jasmin_services", "Role")
    Request = apps.get_model("jasmin_services", "Request")
    RoleObjectPermission = apps.get_model("jasmin_services", "RoleObjectPermission")
    ContentType = apps.get_model("contenttypes", "ContentType")
    Permission = apps.get_model("auth", "Permission")
    RoleContentType = ContentType.objects.get_for_model(Role)
    permission_lookups = (
        dict(content_type=RoleContentType, codename="view_users_role"),
        dict(content_type=RoleContentType, codename="send_message_role"),
        dict(
            content_type=ContentType.objects.get_for_model(Request),
            codename="decide_request",
        ),
    )
    permissions = []
    for lookup in permission_lookups:
        try:
            permissions.append(Permission.objects.get(**lookup))
        except ObjectDoesNotExist:
            pass
    # Process each service in turn
    for service in Service.objects.all():
        migrate_service(RoleObjectPermission, RoleContentType, permissions, service)


class Migration(migrations.Migration):
    dependencies = [
        ("jasmin_services", "0008_flexible_roles_deletions"),
    ]

    operations = [
        migrations.RunPython(migrate),
    ]
