"""
Serializers 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 .models import User, UserProfile, APIKey
import secrets


class UserRegistrationSerializer(serializers.ModelSerializer):
    """Serializer for user registration."""
    password = serializers.CharField(write_only=True, validators=[validate_password])
    password_confirm = serializers.CharField(write_only=True)

    class Meta:
        model = User
        fields = ('username', 'email', 'password', 'password_confirm', 'first_name', 'last_name', 'company_name', 'phone_number')

    def validate(self, attrs):
        if attrs['password'] != attrs['password_confirm']:
            raise serializers.ValidationError("Passwords don't match.")
        return attrs

    def create(self, validated_data):
        validated_data.pop('password_confirm')
        user = User.objects.create_user(**validated_data)
        return user


class UserLoginSerializer(serializers.Serializer):
    """Serializer for user login."""
    email = serializers.EmailField()
    password = serializers.CharField()

    def validate(self, attrs):
        email = attrs.get('email')
        password = attrs.get('password')

        if email and password:
            user = authenticate(username=email, password=password)
            if not user:
                raise serializers.ValidationError('Invalid credentials.')
            if not user.is_active:
                raise serializers.ValidationError('User account is disabled.')
            attrs['user'] = user
            return attrs
        else:
            raise serializers.ValidationError('Must include email and password.')


class UserSerializer(serializers.ModelSerializer):
    """Serializer for user details."""
    profile = serializers.SerializerMethodField()
    usage_limits = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = (
            'id', 'username', 'email', 'first_name', 'last_name', 'subscription_type',
            'is_api_enabled', 'company_name', 'phone_number', 'is_verified',
            'date_joined', 'last_login', 'profile', 'usage_limits'
        )
        read_only_fields = ('id', 'date_joined', 'last_login')

    def get_profile(self, obj):
        try:
            profile = obj.profile
            return UserProfileSerializer(profile).data
        except UserProfile.DoesNotExist:
            return None

    def get_usage_limits(self, obj):
        return obj.get_usage_limits()


class UserProfileSerializer(serializers.ModelSerializer):
    """Serializer for user profile."""
    class Meta:
        model = UserProfile
        fields = (
            'avatar', 'bio', 'website', 'location', 'timezone', 'language',
            'notification_preferences', 'created_at', 'updated_at'
        )
        read_only_fields = ('created_at', 'updated_at')


class UserUpdateSerializer(serializers.ModelSerializer):
    """Serializer for updating user information."""
    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'company_name', 'phone_number')

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        return instance


class PasswordChangeSerializer(serializers.Serializer):
    """Serializer for password change."""
    old_password = serializers.CharField()
    new_password = serializers.CharField(validators=[validate_password])
    new_password_confirm = serializers.CharField()

    def validate(self, attrs):
        if attrs['new_password'] != attrs['new_password_confirm']:
            raise serializers.ValidationError("New passwords don't match.")
        return attrs

    def validate_old_password(self, value):
        user = self.context['request'].user
        if not user.check_password(value):
            raise serializers.ValidationError('Old password is incorrect.')
        return value


class APIKeySerializer(serializers.ModelSerializer):
    """Serializer for API keys."""
    class Meta:
        model = APIKey
        fields = ('id', 'name', 'key', 'is_active', 'last_used', 'created_at', 'expires_at')
        read_only_fields = ('id', 'key', 'last_used', 'created_at')

    def create(self, validated_data):
        validated_data['key'] = secrets.token_urlsafe(32)
        return super().create(validated_data)


class APIKeyCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating API keys."""
    class Meta:
        model = APIKey
        fields = ('name', 'expires_at')

    def create(self, validated_data):
        validated_data['user'] = self.context['request'].user
        validated_data['key'] = secrets.token_urlsafe(32)
        return super().create(validated_data)


class SubscriptionUpdateSerializer(serializers.Serializer):
    """Serializer for updating user subscription."""
    subscription_type = serializers.ChoiceField(choices=[
        ('free', 'Free'),
        ('paid', 'Paid'),
        ('premium', 'Premium'),
    ])

    def validate_subscription_type(self, value):
        user = self.context['request'].user
        if user.subscription_type == value:
            raise serializers.ValidationError('User already has this subscription type.')
        return value

