# example_app/management/commands/seed_data.py

from django.contrib.auth.models import Permission
from django.core.management.base import BaseCommand

from example_app.models import Organization, Project
from topdownrbac.models import Role, RoleBinding, UserSubject


class Command(BaseCommand):
    help = "Seed the database with example users, roles, and permissions"

    def handle(self, *args, **options):
        # Create users
        alice, _ = UserSubject.objects.get_or_create(
            username="alice",
        )
        alice.set_password("secret")
        alice.save()
        bob, _ = UserSubject.objects.get_or_create(
            username="bob",
        )
        bob.set_password("secret")
        bob.save()
        charlie, _ = UserSubject.objects.get_or_create(
            username="charlie",
        )
        charlie.set_password("secret")
        charlie.save()
        self.stdout.write(f"Users: {alice.username}, {bob.username}, {charlie.username}")

        # Populate user profiles (auto-created by the post_save signal)
        alice.profile.bio = "Alice is an org-wide viewer."
        alice.profile.save()
        bob.profile.bio = "Bob is an org-wide editor."
        bob.profile.save()
        charlie.profile.bio = "Charlie can only view one project."
        charlie.profile.save()
        self.stdout.write("User profiles populated.")

        # Create the hierarchy
        # RestrictedObject subclasses must use instantiation + save(),
        # not get_or_create(), because save() delegates to treebeard.
        if not Organization.objects.filter(name="Acme Corp").exists():
            acme = Organization(name="Acme Corp", parent=None)
            acme.save()
        else:
            acme = Organization.objects.get(name="Acme Corp")

        if not Project.objects.filter(name="Website Redesign").exists():
            website = Project(name="Website Redesign", parent=acme)
            website.save()
        else:
            website = Project.objects.get(name="Website Redesign")

        if not Project.objects.filter(name="API Backend").exists():
            api_proj = Project(name="API Backend", parent=acme)
            api_proj.save()
        else:
            api_proj = Project.objects.get(name="API Backend")

        self.stdout.write(f"Hierarchy: {acme.name} -> [{website.name}, {api_proj.name}]")

        # Create roles
        viewer, _ = Role.objects.get_or_create(name="Viewer")
        viewer.add_permission(Permission.objects.get(codename="view_organization"))
        viewer.add_permission(Permission.objects.get(codename="view_project"))

        editor, _ = Role.objects.get_or_create(name="Editor")
        editor.add_many_permissions(
            list(
                Permission.objects.filter(
                    codename__in=[
                        "view_organization",
                        "change_organization",
                        "view_project",
                        "change_project",
                    ]
                )
            )
        )
        self.stdout.write(f"Roles: {viewer.name}, {editor.name}")

        # Give alice Viewer on the whole org tree (propagate=True)
        if not RoleBinding.objects.filter(role=viewer, subject=alice, restricted_object=acme).exists():
            RoleBinding.objects.create(
                role=viewer,
                subject=alice,
                restricted_object=acme,
                propagate=True,
            )

        # Give bob Editor on the whole org tree
        if not RoleBinding.objects.filter(role=editor, subject=bob, restricted_object=acme).exists():
            RoleBinding.objects.create(
                role=editor,
                subject=bob,
                restricted_object=acme,
                propagate=True,
            )
        self.stdout.write("RoleBindings created (propagate=True)")

        # Give charlie Viewer on only the Website Redesign project (no propagation)
        if not RoleBinding.objects.filter(role=viewer, subject=charlie, restricted_object=website).exists():
            RoleBinding.objects.create(
                role=viewer,
                subject=charlie,
                restricted_object=website,
                propagate=False,
            )
        self.stdout.write("RoleBinding for charlie created (propagate=False)")

        # Verify permissions
        assert alice.has_perm("view_organization", acme)
        assert alice.has_perm("view_project", website)
        assert not alice.has_perm("change_project", website)
        assert bob.has_perm("change_project", api_proj)

        # charlie can only view Website Redesign, nothing else
        assert charlie.has_perm("view_project", website)
        assert not charlie.has_perm("view_project", api_proj)
        assert not charlie.has_perm("view_organization", acme)

        self.stdout.write(self.style.SUCCESS("Seed data created and permissions verified."))
