"""
Auth Serializers.
"""
import logging

from django.contrib.auth import authenticate
from rest_framework import serializers

from .models import User

logger = logging.getLogger('apps')


class UserSerializer(serializers.ModelSerializer):
    """User serializer for profile and general user data."""
    is_phone_verified = serializers.BooleanField(read_only=True)
    is_email_verified = serializers.BooleanField(read_only=True)
    
    # Permission & role data — populated lazily
    permissions = serializers.SerializerMethodField()
    roles = serializers.SerializerMethodField()
    is_superuser = serializers.BooleanField(read_only=True)
    
    class Meta:
        model = User
        fields = [
            'id', 'email', 'first_name', 'last_name', 'phone',
            'phone_country_code', 'display_name', 'bio', 'gender',
            'birth_date', 'avatar', 'cover_image',
            'is_active', 'is_superuser',
            'is_phone_verified', 'is_email_verified',
            'phone_verified_at', 'email_verified_at',
            'created_at', 'updated_at', 'last_login_at',
            'preferences', 'full_name',
            'permissions', 'roles',
        ]
        read_only_fields = [
            'id', 'email', 'created_at', 'updated_at', 'last_login_at',
            'phone_verified_at', 'email_verified_at', 'is_superuser',
        ]

    def get_permissions(self, obj) -> list[str]:
        """Return flat list of permission codenames for the user."""
        try:
            from apps.core.permission.services import PermissionService
            return PermissionService.get_user_permissions(obj)
        except Exception:
            logger.warning('Failed to load permissions for user %s', obj.pk)
            return []

    def get_roles(self, obj) -> list[dict]:
        """Return list of role dicts {id, name, slug} for the user."""
        try:
            from apps.core.permission.models import UserRole
            user_roles = UserRole.objects.filter(
                user=obj,
            ).select_related('role').order_by('role__name')
            return [
                {
                    'id': str(ur.role.id),
                    'name': ur.role.name,
                    'slug': ur.role.slug,
                }
                for ur in user_roles
                if ur.is_active()
            ]
        except Exception:
            logger.warning('Failed to load roles for user %s', obj.pk)
            return []


class ProfileUpdateSerializer(serializers.ModelSerializer):
    """Serializer برای بروزرسانی پروفایل."""
    
    class Meta:
        model = User
        fields = [
            'first_name', 'last_name', 'display_name', 'bio',
            'gender', 'birth_date', 'preferences',
        ]


class RegisterSerializer(serializers.ModelSerializer):
    """User registration serializer — email based."""
    password = serializers.CharField(write_only=True, min_length=8)
    password_confirm = serializers.CharField(write_only=True)
    
    class Meta:
        model = User
        fields = ['email', 'password', 'password_confirm', 'first_name', 'last_name', 'phone']
    
    def validate(self, data):
        if data['password'] != data['password_confirm']:
            raise serializers.ValidationError({'password_confirm': 'Passwords do not match'})
        return data
    
    def create(self, validated_data):
        validated_data.pop('password_confirm')
        password = validated_data.pop('password')
        user = User.objects.create_user(password=password, **validated_data)
        return user


class LoginSerializer(serializers.Serializer):
    """User login serializer — email + password."""
    email = serializers.EmailField()
    password = serializers.CharField(write_only=True)
    
    def validate(self, data):
        email = data.get('email')
        password = data.get('password')
        
        user = authenticate(username=email, password=password)
        
        if not user:
            raise serializers.ValidationError('Invalid email or password')
        
        if not user.is_active:
            raise serializers.ValidationError('User account is disabled')
        
        data['user'] = user
        return data


# ─── OTP Serializers ─────────────────────────────────────────────────────


class SendOTPSerializer(serializers.Serializer):
    """ارسال OTP به شماره موبایل."""
    phone = serializers.CharField(max_length=20)


class VerifyOTPSerializer(serializers.Serializer):
    """تأیید OTP و ورود/ثبت‌نام."""
    phone = serializers.CharField(max_length=20)
    code = serializers.CharField(max_length=8)


class PhoneRegisterSerializer(serializers.Serializer):
    """ثبت‌نام با موبایل — اطلاعات تکمیلی پس از verify."""
    phone = serializers.CharField(max_length=20)
    code = serializers.CharField(max_length=8)
    first_name = serializers.CharField(max_length=150, required=False, default='')
    last_name = serializers.CharField(max_length=150, required=False, default='')


class LinkPhoneSerializer(serializers.Serializer):
    """اتصال شماره موبایل به حساب موجود (کاربر باید لاگین باشد)."""
    phone = serializers.CharField(max_length=20)
    code = serializers.CharField(max_length=8)


class AuthSettingsSerializer(serializers.Serializer):
    """تنظیمات عمومی auth (public)."""
    allow_mobile_auth = serializers.BooleanField()
    allow_email_auth = serializers.BooleanField()
    default_auth_method = serializers.CharField()
    default_country = serializers.CharField()
    otp_length = serializers.IntegerField()
    otp_expire_seconds = serializers.IntegerField()
    otp_retry_delay_seconds = serializers.IntegerField()


# ─── User Management Serializers (Admin) ─────────────────────────────


class UserManagementListSerializer(serializers.ModelSerializer):
    """سریالایزر لیست کاربران برای مدیریت."""
    full_name = serializers.CharField(read_only=True)
    has_employee = serializers.SerializerMethodField()
    employee_code = serializers.SerializerMethodField()
    roles = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = [
            'id', 'email', 'first_name', 'last_name', 'full_name',
            'phone', 'is_active', 'is_staff', 'is_superuser',
            'has_employee', 'employee_code', 'roles',
            'created_at', 'last_login_at',
        ]

    def get_has_employee(self, obj) -> bool:
        return hasattr(obj, 'hrm_employee') and obj.hrm_employee is not None

    def get_employee_code(self, obj) -> str | None:
        try:
            return obj.hrm_employee.employee_code if hasattr(obj, 'hrm_employee') and obj.hrm_employee else None
        except Exception:
            return None

    def get_roles(self, obj) -> list[dict]:
        try:
            from apps.core.permission.models import UserRole
            return [
                {'id': str(ur.role.id), 'name': ur.role.name, 'slug': ur.role.slug}
                for ur in UserRole.objects.filter(user=obj).select_related('role')
                if ur.is_active()
            ]
        except Exception:
            return []


class UserManagementDetailSerializer(serializers.ModelSerializer):
    """سریالایزر جزئیات کاربر برای مدیریت."""
    full_name = serializers.CharField(read_only=True)
    has_employee = serializers.SerializerMethodField()
    employee_code = serializers.SerializerMethodField()
    roles = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = [
            'id', 'email', 'first_name', 'last_name', 'full_name',
            'phone', 'display_name', 'gender', 'birth_date',
            'is_active', 'is_staff', 'is_superuser',
            'has_employee', 'employee_code', 'roles',
            'email_verified_at', 'phone_verified_at',
            'created_at', 'updated_at', 'last_login_at',
        ]

    def get_has_employee(self, obj) -> bool:
        return hasattr(obj, 'hrm_employee') and obj.hrm_employee is not None

    def get_employee_code(self, obj) -> str | None:
        try:
            return obj.hrm_employee.employee_code if hasattr(obj, 'hrm_employee') and obj.hrm_employee else None
        except Exception:
            return None

    def get_roles(self, obj) -> list[dict]:
        try:
            from apps.core.permission.models import UserRole
            return [
                {'id': str(ur.role.id), 'name': ur.role.name, 'slug': ur.role.slug}
                for ur in UserRole.objects.filter(user=obj).select_related('role')
                if ur.is_active()
            ]
        except Exception:
            return []


class UserCreateByAdminSerializer(serializers.ModelSerializer):
    """سریالایزر ایجاد کاربر توسط ادمین tenant."""
    password = serializers.CharField(write_only=True, min_length=8)

    class Meta:
        model = User
        fields = [
            'email', 'first_name', 'last_name', 'phone',
            'display_name', 'gender', 'birth_date',
            'password', 'is_active', 'is_staff',
        ]

    def validate_email(self, value):
        if User.objects.filter(email=value).exists():
            raise serializers.ValidationError('این ایمیل قبلاً ثبت شده است.')
        return value

    def validate_phone(self, value):
        if value and User.objects.filter(phone=value).exists():
            raise serializers.ValidationError('این شماره تلفن قبلاً ثبت شده است.')
        return value

    def create(self, validated_data):
        password = validated_data.pop('password')
        user = User(**validated_data)
        user.set_password(password)
        user.save()
        return user


class UserUpdateByAdminSerializer(serializers.ModelSerializer):
    """سریالایزر بروزرسانی کاربر توسط ادمین tenant."""
    password = serializers.CharField(write_only=True, min_length=8, required=False)

    class Meta:
        model = User
        fields = [
            'email', 'first_name', 'last_name', 'phone',
            'display_name', 'gender', 'birth_date',
            'password', 'is_active', 'is_staff',
        ]

    def validate_email(self, value):
        if User.objects.filter(email=value).exclude(pk=self.instance.pk).exists():
            raise serializers.ValidationError('این ایمیل قبلاً ثبت شده است.')
        return value

    def validate_phone(self, value):
        if value and User.objects.filter(phone=value).exclude(pk=self.instance.pk).exists():
            raise serializers.ValidationError('این شماره تلفن قبلاً ثبت شده است.')
        return value

    def update(self, instance, validated_data):
        password = validated_data.pop('password', None)
        for attr, val in validated_data.items():
            setattr(instance, attr, val)
        if password:
            instance.set_password(password)
        instance.save()
        return instance
