from django.contrib.auth.models import Group
import logging

logger = logging.getLogger(__name__)


class UserGroup(Group):
    class Meta:
        verbose_name = "User group"
        verbose_name_plural = "User groups"

    def create_cisa_analyst_group(apps, schema_editor):
        """This method gets run from a data migration."""

        # Hard to pass self to these methods as the calls from migrations
        # are only expecting apps and schema_editor, so we'll just define
        # apps, schema_editor in the local scope instead
        CISA_ANALYST_GROUP_PERMISSIONS = [
            {
                "app_label": "auditlog",
                "model": "logentry",
                "permissions": ["view_logentry"],
            },
            {
                "app_label": "registrar",
                "model": "contact",
                "permissions": ["change_contact"],
            },
            {
                "app_label": "registrar",
                "model": "domainrequest",
                "permissions": ["change_domainrequest"],
            },
            {
                "app_label": "registrar",
                "model": "domain",
                "permissions": ["view_domain"],
            },
            {
                "app_label": "registrar",
                "model": "draftdomain",
                "permissions": ["change_draftdomain"],
            },
            {
                "app_label": "registrar",
                "model": "user",
                "permissions": ["analyst_access_permission", "change_user"],
            },
            {
                "app_label": "registrar",
                "model": "domaininvitation",
                "permissions": ["add_domaininvitation", "view_domaininvitation"],
            },
            {
                "app_label": "registrar",
                "model": "website",
                "permissions": ["change_website"],
            },
            {
                "app_label": "registrar",
                "model": "userdomainrole",
                "permissions": ["view_userdomainrole", "delete_userdomainrole"],
            },
            {
                "app_label": "registrar",
                "model": "verifiedbystaff",
                "permissions": ["add_verifiedbystaff", "change_verifiedbystaff", "delete_verifiedbystaff"],
            },
            {
                "app_label": "registrar",
                "model": "federalagency",
                "permissions": ["add_federalagency", "change_federalagency", "delete_federalagency"],
            },
        ]

        # Avoid error: You can't execute queries until the end
        # of the 'atomic' block.
        # From django docs:
        # https://docs.djangoproject.com/en/4.2/topics/migrations/#data-migrations
        # We can’t import the Person model directly as it may be a newer
        # version than this migration expects. We use the historical version.
        ContentType = apps.get_model("contenttypes", "ContentType")
        Permission = apps.get_model("auth", "Permission")
        UserGroup = apps.get_model("registrar", "UserGroup")

        logger.info("Going to create the Analyst Group")
        try:
            cisa_analysts_group, _ = UserGroup.objects.get_or_create(
                name="cisa_analysts_group",
            )

            cisa_analysts_group.permissions.clear()

            for permission in CISA_ANALYST_GROUP_PERMISSIONS:
                app_label = permission["app_label"]
                model_name = permission["model"]
                permissions = permission["permissions"]

                # Retrieve the content type for the app and model
                content_type = ContentType.objects.get(app_label=app_label, model=model_name)

                # Retrieve the permissions based on their codenames
                permissions = Permission.objects.filter(content_type=content_type, codename__in=permissions)

                # Assign the permissions to the group
                cisa_analysts_group.permissions.add(*permissions)

                # Convert the permissions QuerySet to a list of codenames
                permission_list = list(permissions.values_list("codename", flat=True))

                logger.debug(
                    app_label
                    + " | "
                    + model_name
                    + " | "
                    + ", ".join(permission_list)
                    + " added to group "
                    + cisa_analysts_group.name
                )

                cisa_analysts_group.save()
                logger.debug("CISA Analyst permissions added to group " + cisa_analysts_group.name)
        except Exception as e:
            logger.error(f"Error creating analyst permissions group: {e}")

    def create_full_access_group(apps, schema_editor):
        """This method gets run from a data migration."""

        Permission = apps.get_model("auth", "Permission")
        UserGroup = apps.get_model("registrar", "UserGroup")

        logger.info("Going to create the Full Access Group")
        try:
            full_access_group, _ = UserGroup.objects.get_or_create(
                name="full_access_group",
            )
            # Get all available permissions
            all_permissions = Permission.objects.all()

            # Assign all permissions to the group
            full_access_group.permissions.add(*all_permissions)

            full_access_group.save()
            logger.debug("All permissions added to group " + full_access_group.name)
        except Exception as e:
            logger.error(f"Error creating full access group: {e}")

src/registrar/models/user_group.py
from django.contrib.auth.models import Group
import logging

logger = logging.getLogger(__name__)


class UserGroup(Group):
    """
    UserGroup sets read and write permissions for superusers (who have full access)
    and analysts. For more details, see the dev docs for user-permissions.
    """

    class Meta:
        verbose_name = "User group"
        verbose_name_plural = "User groups"

    def create_cisa_analyst_group(apps, schema_editor):
        """This method gets run from a data migration."""

        # Hard to pass self to these methods as the calls from migrations
        # are only expecting apps and schema_editor, so we'll just define
        # apps, schema_editor in the local scope instead
        CISA_ANALYST_GROUP_PERMISSIONS = [
            {
                "app_label": "auditlog",
                "model": "logentry",
                "permissions": ["view_logentry"],
            },
            {
                "app_label": "registrar",
                "model": "contact",
                "permissions": ["change_contact"],
            },
            {
                "app_label": "registrar",
                "model": "domaininformation",
                "permissions": ["change_domaininformation"],
            },
            {
                "app_label": "registrar",
                "model": "domainrequest",
                "permissions": ["change_domainrequest"],
            },
            {
                "app_label": "registrar",
                "model": "domain",
                "permissions": ["view_domain"],
            },
            {
                "app_label": "registrar",
                "model": "draftdomain",
                "permissions": ["change_draftdomain"],
            },
            {
                "app_label": "registrar",
                "model": "user",
                "permissions": ["analyst_access_permission", "change_user"],
            },
            {
                "app_label": "registrar",
                "model": "domaininvitation",
                "permissions": ["add_domaininvitation", "view_domaininvitation"],
            },
            {
                "app_label": "registrar",
                "model": "website",
                "permissions": ["change_website"],
            },
            {
                "app_label": "registrar",
                "model": "userdomainrole",
                "permissions": ["view_userdomainrole", "delete_userdomainrole"],
            },
            {
                "app_label": "registrar",
                "model": "verifiedbystaff",
                "permissions": ["add_verifiedbystaff", "change_verifiedbystaff", "delete_verifiedbystaff"],
            },
            {
                "app_label": "registrar",
                "model": "federalagency",
                "permissions": ["add_federalagency", "change_federalagency", "delete_federalagency"],
            },
        ]

        # Avoid error: You can't execute queries until the end
        # of the 'atomic' block.
        # From django docs:
        # https://docs.djangoproject.com/en/4.2/topics/migrations/#data-migrations
        # We can’t import the Person model directly as it may be a newer
        # version than this migration expects. We use the historical version.
        ContentType = apps.get_model("contenttypes", "ContentType")
        Permission = apps.get_model("auth", "Permission")
        UserGroup = apps.get_model("registrar", "UserGroup")

        logger.info("Going to create the Analyst Group")
        try:
            cisa_analysts_group, _ = UserGroup.objects.get_or_create(
                name="cisa_analysts_group",
            )

            cisa_analysts_group.permissions.clear()

            for permission in CISA_ANALYST_GROUP_PERMISSIONS:
                app_label = permission["app_label"]
                model_name = permission["model"]
                permissions = permission["permissions"]

                # Retrieve the content type for the app and model
                content_type = ContentType.objects.get(app_label=app_label, model=model_name)

                # Retrieve the permissions based on their codenames
                permissions = Permission.objects.filter(content_type=content_type, codename__in=permissions)

                # Assign the permissions to the group
                cisa_analysts_group.permissions.add(*permissions)

                # Convert the permissions QuerySet to a list of codenames
                permission_list = list(permissions.values_list("codename", flat=True))

                logger.debug(
                    app_label
                    + " | "
                    + model_name
                    + " | "
                    + ", ".join(permission_list)
                    + " added to group "
                    + cisa_analysts_group.name
                )

                cisa_analysts_group.save()
                logger.debug("CISA Analyst permissions added to group " + cisa_analysts_group.name)
        except Exception as e:
            logger.error(f"Error creating analyst permissions group: {e}")

    def create_full_access_group(apps, schema_editor):
        """This method gets run from a data migration."""

        Permission = apps.get_model("auth", "Permission")
        UserGroup = apps.get_model("registrar", "UserGroup")

        logger.info("Going to create the Full Access Group")
        try:
            full_access_group, _ = UserGroup.objects.get_or_create(
                name="full_access_group",
            )
            # Get all available permissions
            all_permissions = Permission.objects.all()

            # Assign all permissions to the group
            full_access_group.permissions.add(*all_permissions)

            full_access_group.save()
            logger.debug("All permissions added to group " + full_access_group.name)
        except Exception as e:
            logger.error(f"Error creating full access group: {e}")

src/registrar/models/user_group.py
diff --git a/docs/developer/user-permissions.md b/docs/developer/user-permissions.md
index f7c41492d..4919c02ff 100644
--- a/docs/developer/user-permissions.md
+++ b/docs/developer/user-permissions.md
@@ -19,6 +19,18 @@ role or set of permissions that they have. We use a `UserDomainRole`
 `User.domains` many-to-many relationship that works through the
 `UserDomainRole` link table.
 
+## Migrating changes to Analyst Permissions model
+Analysts are allowed a certain set of read/write registrar permissions. 
+Setting user permissions requires a migration to change the UserGroup 
+and Permission models, which requires us to manually make a migration 
+file for user permission changes. 
+To update analyst permissions do the following:
+1. Make desired changes to analyst group permissions in user_group.py.
+2. Follow the steps in the migration file0037_create_groups_v01.py to 
+create a duplicate migration for the updated user group permissions.
+3. To migrate locally, run docker-compose up. To migrate on a sandbox,
+push the new migration onto your sandbox before migrating.
+
 ## Permission decorator
 
 The Django objects that need to be permission controlled are various views.
diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py
index 2aa2f642e..8565ea288 100644
--- a/src/registrar/models/user_group.py
+++ b/src/registrar/models/user_group.py
@@ -5,6 +5,11 @@
 
 
 class UserGroup(Group):
+    """
+    UserGroup sets read and write permissions for superusers (who have full access)
+    and analysts. For more details, see the dev docs for user-permissions.
+    """
+
     class Meta:
         verbose_name = "User group"
         verbose_name_plural = "User groups"

Provide documentation about user_groups and permission changes
### Issue description

If we edit permissions for User Groups, such as to make different items viewable on django admin, this requires a very specific set of instructions that is only documentated inside user group migration files. We should reference this documentation somewhere else in our developer readme so it's clear what is needed to be done if you ever change permissions in the future.

 We had a case where permissions were changed and it wasn't clear what needed to be done (make a manual migration). The developers lost time trying to figure out why permissions didn't show and why running makemigrations changed nothing. I suggest adding an inline code comment around where permissions are set in user_groups too that points to documentation in developer readme. This may save future developer's time.

### Acceptance criteria

- [ ] update developer documentation (inline and md) about user_group/ permission changes

### Additional context
the migration files that have documentation about this are all ones that say _create_groups_v (followed by a number), such as 0075_create_groups_v08.py. See those for the current documentation and note that this was hard for developers to find.
[Slack thread](https://cisa-corp.slack.com/archives/C05BGB4L5NF/p1709939481415349)

### Links to other issues

_No response_
