from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from rest_framework.test import APIClient

from basic_info import models as basic_models


User = get_user_model()


class CoreAPITestCase(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.merchant = basic_models.Merchant.objects.create(
            name="核心商户",
            type=basic_models.MerchantTypeEnum.STORE,
        )
        self.other_merchant = basic_models.Merchant.objects.create(
            name="其他商户",
            type=basic_models.MerchantTypeEnum.STORE,
        )
        self.super_user = User.objects.create_superuser(
            username="core_admin",
            password="pass12345",
            email="core@example.com",
        )
        self.employee = basic_models.Employee.objects.create(
            merchant=self.merchant,
            sys_user=self.super_user,
            name="核心管理员",
        )
        self.normal_user = User.objects.create_user(username="normal", password="pass12345")
        self.no_employee_super_user = User.objects.create_superuser(
            username="no_employee_admin",
            password="pass12345",
        )

    def authenticate_super_admin(self):
        self.client.force_authenticate(user=self.super_user)

    def test_core_api_requires_superuser_and_employee_merchant(self):
        response = self.client.get("/api/core/users/")
        self.assertEqual(response.status_code, 401)

        self.client.force_authenticate(user=self.normal_user)
        response = self.client.get("/api/core/users/")
        self.assertEqual(response.status_code, 403)

        self.client.force_authenticate(user=self.no_employee_super_user)
        response = self.client.get("/api/core/users/")
        self.assertEqual(response.status_code, 403)

    def test_user_list_is_merchant_scoped(self):
        same_user = User.objects.create_user(username="same_merchant", password="pass12345")
        basic_models.UserProfile.objects.create(user=same_user, merchant=self.merchant)

        other_user = User.objects.create_user(username="other_merchant", password="pass12345")
        basic_models.UserProfile.objects.create(user=other_user, merchant=self.other_merchant)

        self.authenticate_super_admin()
        response = self.client.get("/api/core/users/", {"limit": 100})
        self.assertEqual(response.status_code, 200)
        usernames = {item["username"] for item in response.data["results"]}
        self.assertIn("core_admin", usernames)
        self.assertIn("same_merchant", usernames)
        self.assertNotIn("other_merchant", usernames)

        detail_response = self.client.get(f"/api/core/users/{other_user.id}/")
        self.assertEqual(detail_response.status_code, 404)

    def test_create_user_creates_profile_but_not_employee(self):
        group = Group.objects.create(name="核心角色")
        self.authenticate_super_admin()
        response = self.client.post(
            "/api/core/users/",
            {
                "username": "core_created",
                "password": "pass12345",
                "email": "created@example.com",
                "first_name": "Core",
                "is_active": True,
                "groups": [group.id],
            },
            format="json",
        )
        self.assertEqual(response.status_code, 201)

        user = User.objects.get(username="core_created")
        self.assertEqual(user.profile.merchant, self.merchant)
        self.assertFalse(hasattr(user, "employee"))
        self.assertIn(group, user.groups.all())

    def test_user_cannot_be_deleted_and_self_cannot_be_deactivated_or_demoted(self):
        self.authenticate_super_admin()
        response = self.client.delete(f"/api/core/users/{self.super_user.id}/")
        self.assertEqual(response.status_code, 405)

        response = self.client.patch(
            f"/api/core/users/{self.super_user.id}/",
            {"is_active": False},
            format="json",
        )
        self.assertEqual(response.status_code, 400)
        self.assertIn("is_active", response.data)

        response = self.client.patch(
            f"/api/core/users/{self.super_user.id}/",
            {"is_superuser": False},
            format="json",
        )
        self.assertEqual(response.status_code, 400)
        self.assertIn("is_superuser", response.data)

    def test_groups_are_global_full_crud(self):
        content_type = ContentType.objects.get_for_model(User)
        permission = Permission.objects.get(content_type=content_type, codename="view_user")
        self.authenticate_super_admin()

        create_response = self.client.post(
            "/api/core/groups/",
            {"name": "全局核心组", "permissions": [permission.id]},
            format="json",
        )
        self.assertEqual(create_response.status_code, 201)
        group_id = create_response.data["id"]

        detail_response = self.client.get(f"/api/core/groups/{group_id}/")
        self.assertEqual(detail_response.status_code, 200)
        self.assertEqual(detail_response.data["name"], "全局核心组")
        self.assertEqual(detail_response.data["permissions"], [permission.id])

        patch_response = self.client.patch(
            f"/api/core/groups/{group_id}/",
            {"name": "已更新核心组"},
            format="json",
        )
        self.assertEqual(patch_response.status_code, 200)
        self.assertEqual(patch_response.data["name"], "已更新核心组")

        delete_response = self.client.delete(f"/api/core/groups/{group_id}/")
        self.assertEqual(delete_response.status_code, 204)
        self.assertFalse(Group.objects.filter(id=group_id).exists())

    def test_permissions_are_read_only(self):
        content_type = ContentType.objects.get_for_model(User)
        permission = Permission.objects.get(content_type=content_type, codename="view_user")
        self.authenticate_super_admin()

        list_response = self.client.get("/api/core/permissions/", {"limit": 100})
        self.assertEqual(list_response.status_code, 200)
        self.assertTrue(any(item["id"] == permission.id for item in list_response.data["results"]))

        detail_response = self.client.get(f"/api/core/permissions/{permission.id}/")
        self.assertEqual(detail_response.status_code, 200)
        self.assertEqual(detail_response.data["full_code"], "auth.view_user")

        create_response = self.client.post(
            "/api/core/permissions/",
            {"name": "fake", "codename": "fake_permission", "content_type": content_type.id},
            format="json",
        )
        self.assertEqual(create_response.status_code, 405)

        patch_response = self.client.patch(
            f"/api/core/permissions/{permission.id}/",
            {"name": "renamed"},
            format="json",
        )
        self.assertEqual(patch_response.status_code, 405)

        delete_response = self.client.delete(f"/api/core/permissions/{permission.id}/")
        self.assertEqual(delete_response.status_code, 405)
