"""Accounts Serializers

This module contains serializers for the accounts app API endpoints.
These serializers handle data serialization and validation for user-related models.
"""

from rest_framework import serializers
from django.contrib.auth import authenticate
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from .models import User, UserProfile, UserSession
from apps.core.serializers import BaseSerializer


class UserProfileSerializer(BaseSerializer):
    """Serializer for UserProfile model."""
    
    class Meta:
        model = UserProfile
        fields = [
            'job_title', 'company', 'department', 'website', 'linkedin',
            'address_line1', 'address_line2', 'city', 'state', 'postal_code',
            'country', 'created_at', 'updated_at'
        ]
        read_only_fields = ['created_at', 'updated_at']


class UserSerializer(BaseSerializer):
    """Serializer for User model."""
    
    profile = UserProfileSerializer(read_only=True)
    password = serializers.CharField(write_only=True, validators=[validate_password])
    password_confirm = serializers.CharField(write_only=True)
    full_name = serializers.CharField(source='get_full_name', read_only=True)
    
    class Meta:
        model = User
        fields = [
            'id', 'username', 'email', 'first_name', 'last_name', 'full_name',
            'phone_number', 'avatar', 'bio', 'timezone_field', 'language',
            'is_verified', 'is_active', 'date_joined', 'last_login',
            'password', 'password_confirm', 'profile'
        ]
        read_only_fields = [
            'id', 'is_verified', 'date_joined', 'last_login', 'full_name'
        ]
        extra_kwargs = {
            'password': {'write_only': True},
            'email': {'required': True},
        }
    
    def validate(self, attrs):
        """Validate the serializer data."""
        # Check password confirmation
        if 'password' in attrs and 'password_confirm' in attrs:
            if attrs['password'] != attrs['password_confirm']:
                raise serializers.ValidationError({
                    'password_confirm': _('Password confirmation does not match.')
                })
        
        # Remove password_confirm from validated data
        attrs.pop('password_confirm', None)
        
        return attrs
    
    def validate_email(self, value):
        """Validate email uniqueness."""
        value = value.lower()
        
        # Check if email is already taken (excluding current user)
        queryset = User.objects.filter(email=value)
        if self.instance:
            queryset = queryset.exclude(pk=self.instance.pk)
        
        if queryset.exists():
            raise serializers.ValidationError(
                _('A user with this email already exists.')
            )
        
        return value
    
    def validate_username(self, value):
        """Validate username uniqueness."""
        # Check if username is already taken (excluding current user)
        queryset = User.objects.filter(username=value)
        if self.instance:
            queryset = queryset.exclude(pk=self.instance.pk)
        
        if queryset.exists():
            raise serializers.ValidationError(
                _('A user with this username already exists.')
            )
        
        return value
    
    def create(self, validated_data):
        """Create a new user."""
        password = validated_data.pop('password')
        user = User.objects.create_user(password=password, **validated_data)
        
        # Create user profile
        UserProfile.objects.create(user=user)
        
        return user
    
    def update(self, instance, validated_data):
        """Update an existing user."""
        password = validated_data.pop('password', None)
        
        # Update user fields
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        
        # Update password if provided
        if password:
            instance.set_password(password)
        
        instance.save()
        return instance


class UserRegistrationSerializer(serializers.ModelSerializer):
    """Serializer for user registration."""
    
    password = serializers.CharField(
        write_only=True,
        validators=[validate_password],
        style={'input_type': 'password'}
    )
    password_confirm = serializers.CharField(
        write_only=True,
        style={'input_type': 'password'}
    )
    
    class Meta:
        model = User
        fields = [
            'username', 'email', 'first_name', 'last_name',
            'password', 'password_confirm'
        ]
        extra_kwargs = {
            'email': {'required': True},
            'first_name': {'required': True},
            'last_name': {'required': True},
        }
    
    def validate(self, attrs):
        """Validate registration data."""
        if attrs['password'] != attrs['password_confirm']:
            raise serializers.ValidationError({
                'password_confirm': _('Password confirmation does not match.')
            })
        
        attrs.pop('password_confirm')
        return attrs
    
    def validate_email(self, value):
        """Validate email uniqueness."""
        value = value.lower()
        if User.objects.filter(email=value).exists():
            raise serializers.ValidationError(
                _('A user with this email already exists.')
            )
        return value
    
    def validate_username(self, value):
        """Validate username uniqueness."""
        if User.objects.filter(username=value).exists():
            raise serializers.ValidationError(
                _('A user with this username already exists.')
            )
        return value
    
    def create(self, validated_data):
        """Create a new user account."""
        password = validated_data.pop('password')
        user = User.objects.create_user(password=password, **validated_data)
        
        # Create user profile
        UserProfile.objects.create(user=user)
        
        return user


class LoginSerializer(serializers.Serializer):
    """Serializer for user login."""
    
    email = serializers.EmailField()
    password = serializers.CharField(
        style={'input_type': 'password'},
        trim_whitespace=False
    )
    
    def validate(self, attrs):
        """Validate login credentials."""
        email = attrs.get('email')
        password = attrs.get('password')
        
        if email and password:
            # Authenticate using email
            user = authenticate(
                request=self.context.get('request'),
                username=email,
                password=password
            )
            
            if not user:
                raise serializers.ValidationError(
                    _('Invalid email or password.'),
                    code='authorization'
                )
            
            if not user.is_active:
                raise serializers.ValidationError(
                    _('User account is disabled.'),
                    code='authorization'
                )
            
            attrs['user'] = user
            return attrs
        else:
            raise serializers.ValidationError(
                _('Must include email and password.'),
                code='authorization'
            )


class PasswordChangeSerializer(serializers.Serializer):
    """Serializer for password change."""
    
    old_password = serializers.CharField(
        style={'input_type': 'password'},
        trim_whitespace=False
    )
    new_password = serializers.CharField(
        validators=[validate_password],
        style={'input_type': 'password'},
        trim_whitespace=False
    )
    new_password_confirm = serializers.CharField(
        style={'input_type': 'password'},
        trim_whitespace=False
    )
    
    def validate_old_password(self, value):
        """Validate the old password."""
        user = self.context['request'].user
        if not user.check_password(value):
            raise serializers.ValidationError(
                _('Current password is incorrect.')
            )
        return value
    
    def validate(self, attrs):
        """Validate password change data."""
        if attrs['new_password'] != attrs['new_password_confirm']:
            raise serializers.ValidationError({
                'new_password_confirm': _('New password confirmation does not match.')
            })
        
        return attrs
    
    def save(self):
        """Change the user's password."""
        user = self.context['request'].user
        user.set_password(self.validated_data['new_password'])
        user.save()
        return user


class UserSessionSerializer(BaseSerializer):
    """Serializer for UserSession model."""
    
    is_current = serializers.SerializerMethodField()
    is_expired = serializers.SerializerMethodField()
    
    class Meta:
        model = UserSession
        fields = [
            'id', 'session_key', 'ip_address', 'user_agent',
            'is_active', 'is_current', 'is_expired',
            'created_at', 'expires_at'
        ]
        read_only_fields = ['id', 'session_key', 'created_at']
    
    def get_is_current(self, obj):
        """Check if this is the current session."""
        request = self.context.get('request')
        if request and hasattr(request, 'session'):
            return obj.session_key == request.session.session_key
        return False
    
    def get_is_expired(self, obj):
        """Check if the session has expired."""
        return obj.is_expired()


class UserListSerializer(BaseSerializer):
    """Simplified serializer for user lists."""
    
    full_name = serializers.CharField(source='get_full_name', read_only=True)
    
    class Meta:
        model = User
        fields = [
            'id', 'username', 'email', 'first_name', 'last_name',
            'full_name', 'avatar', 'is_active', 'date_joined'
        ]
        read_only_fields = ['id', 'date_joined', 'full_name']


class UserDetailSerializer(UserSerializer):
    """Detailed serializer for user detail views."""
    
    sessions_count = serializers.SerializerMethodField()
    last_login_formatted = serializers.SerializerMethodField()
    
    class Meta(UserSerializer.Meta):
        fields = UserSerializer.Meta.fields + [
            'sessions_count', 'last_login_formatted'
        ]
    
    def get_sessions_count(self, obj):
        """Get the count of active sessions."""
        return obj.sessions.filter(is_active=True).count()
    
    def get_last_login_formatted(self, obj):
        """Get formatted last login date."""
        if obj.last_login:
            return obj.last_login.strftime('%Y-%m-%d %H:%M:%S')
        return None