from ichec_django_core.models import Member, Organization, Address

from ichec_django_core.client.resources import create_organizations
from ichec_django_core.test import (
    setup_default_users_and_groups,
    setup_default_organizations,
    add_group_permissions,
    AuthAPITestCase,
)


class TestOrganizationView(AuthAPITestCase):

    template = create_organizations(1)[0]

    def setUp(self):
        self.url = "/api/organizations/"

        setup_default_users_and_groups()

        add_group_permissions(
            "admins",
            Organization,
            ["change_organization", "add_organization", "delete_organization"],
        )

        add_group_permissions(
            "members",
            Organization,
            ["view_organization"],
        )

        orgs = setup_default_organizations(Member.objects.get(username="other_user"))
        self.internal_org, self.public_org, self.inactive_org = orgs

    def test_list_access(self):

        scenarios = (
            ["", 1, 200, "Public can list public items"],
            ["regular_user", 1, 200, "Registered can list public items"],
            ["member", 2, 200, "Member can list all items"],
            ["other_user", 2, 200, "Item member can list item"],
        )
        for user, count, status, msg in scenarios:
            if user:
                response = self.assert_status(self.auth_list(user), status, msg)
            else:
                response = self.assert_status(self.public_list(), status, msg)

            self.assertEqual(response.body.count, count, msg)

    def test_detail_access(self):

        public = self.public_org.id
        internal = self.internal_org.id
        scenarios = (
            ["", public, "public", 200, "Public can view public item"],
            ["", internal, "public", 404, "Public can't view internal item"],
            ["regular_user", public, "public", 200, "Registered can view public item"],
            [
                "regular_user",
                internal,
                "public",
                404,
                "Registered can't view internal item",
            ],
            ["member", public, "", 200, "Member can view public item"],
            ["member", internal, "", 200, "Item Member can view internal item"],
            ["other_user", internal, "", 200, "Item member can view item"],
        )

        for user, item, role, status, msg in scenarios:
            if user:
                self.assert_status(self.auth_detail(user, item, role), status, msg)
            else:
                self.assert_status(self.detail(item, role), status, msg)

    def test_create_permissions(self):

        scenarios = (
            ["", 401, "Public can't create, no auth"],
            ["regular_user", 403, "Registered can't create, no perm"],
            ["admin_user", 201, "Admin can create"],
        )

        for user, status, msg in scenarios:
            if user:
                self.assert_status(self.auth_create(user, self.template), status, msg)
            else:
                self.assert_status(self.create(self.template), status, msg)

    def _create_for_update(
        self, creator, members: list | None = None, member_key: str = "members"
    ):

        if members:
            template = self.template.model_copy(
                update={"members": [self.get_member_url(m) for m in members]}
            )
        else:
            template = self.template

        created = self.assert_201(self.auth_create(creator, template)).body
        return created.model_copy(
            update={"address": created.address.model_copy(update={"country": "FR"})}
        )

    def _verify_update(self, updated):
        self.assertEqual(updated.body.address.country, "FR")

    def test_update_permissions(self):

        scenarios = (
            ["", 401, False, "Public can't update, no auth"],
            ["regular_user", 404, False, "Registered can't update, no list"],
            ["other_user", 200, True, "Item member can update"],
            ["admin_user", 200, False, "Admin can update"],
        )

        for user, status, member, msg in scenarios:
            print(msg)
            if member:
                created = self._create_for_update("admin_user", [user])
            else:
                created = self._create_for_update("admin_user")

            print(created)

            updated = None
            if user:
                updated = self.assert_status(
                    self.auth_update(user, created.id, created), status, msg
                )
            else:
                self.assert_status(self.update(created.id, created), status, msg)

            if updated:
                self._verify_update(updated)

    def test_delete_permissions(self):

        scenarios = (
            ["", 401, False, "Public can't delete, no auth"],
            ["regular_user", 403, False, "Registered can't delete"],
            ["other_user", 403, True, "Item member can't delete"],
            ["admin_user", 204, False, "Admin can delete"],
        )

        for user, status, member, msg in scenarios:
            if member:
                created = self._create_for_update("admin_user", [user])
            else:
                created = self._create_for_update("admin_user")

            if user:
                self.assert_status(self.auth_delete(user, created.id), status, msg)
            else:
                self.assert_status(self.delete(created.id), status, msg)

    def test_filters(self):
        pass

    def test_fields(self):
        pass
