from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django.db import transaction
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_field

from basic_info.models import UserProfile


User = get_user_model()


class CorePermissionSerializer(serializers.ModelSerializer):
    app_label = serializers.CharField(source="content_type.app_label", read_only=True)
    model = serializers.CharField(source="content_type.model", read_only=True)
    full_code = serializers.SerializerMethodField()

    class Meta:
        model = Permission
        fields = [
            "id",
            "name",
            "codename",
            "content_type",
            "app_label",
            "model",
            "full_code",
        ]
        read_only_fields = fields

    def get_full_code(self, obj) -> str:
        return f"{obj.content_type.app_label}.{obj.codename}"


class CoreGroupSerializer(serializers.ModelSerializer):
    permissions = serializers.PrimaryKeyRelatedField(
        many=True,
        queryset=Permission.objects.select_related("content_type").all(),
        required=False,
    )
    permission_details = CorePermissionSerializer(
        source="permissions",
        many=True,
        read_only=True,
    )

    class Meta:
        model = Group
        fields = ["id", "name", "permissions", "permission_details"]


class CoreUserSerializer(serializers.ModelSerializer):
    groups = serializers.PrimaryKeyRelatedField(
        many=True,
        queryset=Group.objects.all(),
        required=False,
    )
    user_permissions = serializers.PrimaryKeyRelatedField(
        many=True,
        queryset=Permission.objects.select_related("content_type").all(),
        required=False,
    )
    password = serializers.CharField(write_only=True, required=False, min_length=6)
    merchant_id = serializers.IntegerField(source="profile.merchant_id", read_only=True)
    employee_id = serializers.IntegerField(source="employee.id", read_only=True)
    employee_name = serializers.CharField(source="employee.name", read_only=True)
    group_details = serializers.SerializerMethodField()
    permission_details = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = [
            "id",
            "username",
            "email",
            "first_name",
            "last_name",
            "is_active",
            "is_staff",
            "is_superuser",
            "last_login",
            "date_joined",
            "merchant_id",
            "employee_id",
            "employee_name",
            "groups",
            "group_details",
            "user_permissions",
            "permission_details",
            "password",
        ]
        read_only_fields = [
            "id",
            "last_login",
            "date_joined",
            "merchant_id",
            "employee_id",
            "employee_name",
            "group_details",
            "permission_details",
        ]

    @extend_schema_field(serializers.ListField(child=serializers.DictField()))
    def get_group_details(self, obj) -> list[dict[str, object]]:
        return [{"id": group.id, "name": group.name} for group in obj.groups.all()]

    @extend_schema_field(CorePermissionSerializer(many=True))
    def get_permission_details(self, obj) -> list[dict[str, object]]:
        permissions = obj.user_permissions.select_related("content_type").all()
        return CorePermissionSerializer(permissions, many=True).data

    def validate_username(self, value):
        queryset = User.objects.filter(username=value)
        if self.instance is not None:
            queryset = queryset.exclude(pk=self.instance.pk)
        if queryset.exists():
            raise serializers.ValidationError("用户名已存在")
        return value

    def validate(self, attrs):
        request = self.context.get("request")
        current_user = getattr(request, "user", None)
        target_user = self.instance

        if current_user is not None and target_user is not None and current_user.pk == target_user.pk:
            if attrs.get("is_active") is False:
                raise serializers.ValidationError({"is_active": "不能停用当前登录用户"})
            if attrs.get("is_superuser") is False:
                raise serializers.ValidationError({"is_superuser": "不能取消当前登录用户的 superuser 权限"})

        return attrs

    def create(self, validated_data):
        groups = validated_data.pop("groups", [])
        user_permissions = validated_data.pop("user_permissions", [])
        password = validated_data.pop("password", None)
        merchant = self.context["merchant"]

        with transaction.atomic():
            user = User(**validated_data)
            if password:
                user.set_password(password)
            else:
                user.set_unusable_password()
            user.save()
            if groups:
                user.groups.set(groups)
            if user_permissions:
                user.user_permissions.set(user_permissions)
            UserProfile.objects.create(user=user, merchant=merchant)

        return user

    def update(self, instance, validated_data):
        groups = validated_data.pop("groups", None)
        user_permissions = validated_data.pop("user_permissions", None)
        password = validated_data.pop("password", None)

        with transaction.atomic():
            for attr, value in validated_data.items():
                setattr(instance, attr, value)
            if password:
                instance.set_password(password)
            instance.save()
            if groups is not None:
                instance.groups.set(groups)
            if user_permissions is not None:
                instance.user_permissions.set(user_permissions)

        return instance

