"""
Django REST Framework Serializers for TheStarFX models.

Serializers handle the conversion between Python objects and JSON for API responses.
"""
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password
from rest_framework import serializers
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from .models import (
    Bot,
    ContentBlock,
    SiteSettings,
    NavigationItem,
    ForexPair,
    Lesson,
    Signal,
    News,
    Testimonial,
    LeaderboardEntry,
)


# ---------------------------------------------------------------------------
# Auth Serializers
# ---------------------------------------------------------------------------

class RegisterSerializer(serializers.ModelSerializer):
    """Serializer for new user registration (name, email, password)."""

    name = serializers.CharField(write_only=True, required=True)
    password = serializers.CharField(
        write_only=True, required=True, validators=[validate_password]
    )
    password2 = serializers.CharField(write_only=True, required=True, label='Confirm password')

    class Meta:
        model = User
        fields = ['name', 'email', 'password', 'password2']
        extra_kwargs = {'email': {'required': True}}

    def validate_email(self, value):
        if User.objects.filter(email__iexact=value).exists():
            raise serializers.ValidationError('A user with this email already exists.')
        return value.lower()

    def validate(self, attrs):
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError({'password': 'Passwords do not match.'})
        return attrs

    def create(self, validated_data):
        name = validated_data.pop('name')
        validated_data.pop('password2')
        email = validated_data['email']

        # Use email as username (unique); split name into first/last
        parts = name.strip().split(' ', 1)
        first_name = parts[0]
        last_name  = parts[1] if len(parts) > 1 else ''

        user = User.objects.create_user(
            username=email,
            email=email,
            password=validated_data['password'],
            first_name=first_name,
            last_name=last_name,
        )
        return user


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    """Extend the JWT payload with basic user info."""

    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['name']  = f'{user.first_name} {user.last_name}'.strip()
        token['email'] = user.email
        token['is_staff'] = user.is_staff
        return token

    def validate(self, attrs):
        # Allow login with email instead of username
        email = attrs.get('username', '').lower()
        try:
            user = User.objects.get(email__iexact=email)
            attrs['username'] = user.username
        except User.DoesNotExist:
            pass
        return super().validate(attrs)


class UserProfileSerializer(serializers.ModelSerializer):
    """Read-only serializer for the authenticated user's profile."""

    name = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ['id', 'name', 'email', 'date_joined', 'is_staff', 'is_superuser']
        read_only_fields = fields

    def get_name(self, obj):
        return f'{obj.first_name} {obj.last_name}'.strip() or obj.username


class GoogleLoginSerializer(serializers.Serializer):
    """Credential returned by Google Identity Services in the browser."""

    credential = serializers.CharField(trim_whitespace=True)


class LogoutSerializer(serializers.Serializer):
    """Refresh token to revoke when ending a JWT session."""

    refresh = serializers.CharField(trim_whitespace=True)


class ContentBlockSerializer(serializers.ModelSerializer):
    """Serializer for editable public website copy."""

    class Meta:
        model = ContentBlock
        fields = [
            'id', 'key', 'page', 'section', 'eyebrow', 'title',
            'highlight_text', 'body', 'primary_cta_label', 'primary_cta_url',
            'secondary_cta_label', 'secondary_cta_url', 'content_json',
            'display_order', 'is_published', 'created_at', 'updated_at',
        ]
        read_only_fields = ['created_at', 'updated_at']


class SiteSettingsSerializer(serializers.ModelSerializer):
    class Meta:
        model = SiteSettings
        fields = [
            'id', 'key', 'site_name', 'site_tagline', 'logo_url',
            'footer_description', 'support_email', 'support_location',
            'copyright_text', 'sign_in_label', 'register_label',
            'learn_menu_label', 'more_menu_label', 'footer_platform_label',
            'footer_learn_label', 'footer_contact_label', 'telegram_url',
            'discord_url', 'x_url', 'instagram_url', 'updated_at',
        ]
        read_only_fields = ['updated_at']


class NavigationItemSerializer(serializers.ModelSerializer):
    location_label = serializers.CharField(source='get_location_display', read_only=True)

    class Meta:
        model = NavigationItem
        fields = [
            'id', 'label', 'url', 'location', 'location_label',
            'description', 'icon', 'order', 'is_active', 'open_new_tab',
            'created_at', 'updated_at',
        ]
        read_only_fields = ['created_at', 'updated_at']


class BotSerializer(serializers.ModelSerializer):
    """Serializer for Trading Bot model."""
    
    class Meta:
        model = Bot
        fields = [
            'id', 'name', 'description', 'category', 'pairs', 'timeframe',
            'win_rate', 'total_trades', 'avg_profit', 'max_drawdown',
            'monthly_return', 'price', 'plan', 'status', 'backtest_years',
            'sharpe_ratio', 'badge', 'tags', 'chart_data', 'created_at', 'updated_at'
        ]
        read_only_fields = ['created_at', 'updated_at']


class ForexPairSerializer(serializers.ModelSerializer):
    """Serializer for Forex Pair model."""
    
    class Meta:
        model = ForexPair
        fields = [
            'id', 'pair', 'base', 'quote', 'price', 'change', 'change_pct',
            'bid', 'ask', 'spread', 'high', 'low', 'volume', 'trend',
            'symbol1', 'symbol2', 'color1', 'color2', 'category', 'sentiment',
            'created_at', 'updated_at'
        ]
        read_only_fields = ['created_at', 'updated_at']


class LessonSerializer(serializers.ModelSerializer):
    """Serializer for Lesson model."""
    
    class Meta:
        model = Lesson
        fields = [
            'id', 'title', 'description', 'category', 'difficulty',
            'image_url', 'video_url', 'content', 'duration_minutes',
            'order', 'tags', 'created_at', 'updated_at'
        ]
        read_only_fields = ['created_at', 'updated_at']


class SignalSerializer(serializers.ModelSerializer):
    """Serializer for Trading Signal model."""
    
    class Meta:
        model = Signal
        fields = [
            'id', 'pair', 'signal_type', 'confidence', 'entry_price',
            'stop_loss', 'take_profit', 'reason', 'chart_pattern',
            'created_at', 'expires_at'
        ]
        read_only_fields = ['created_at']


class NewsSerializer(serializers.ModelSerializer):
    """Serializer for News model."""
    
    class Meta:
        model = News
        fields = [
            'id', 'title', 'content', 'source', 'image_url',
            'category', 'impact', 'related_pairs',
            'created_at', 'published_at'
        ]
        read_only_fields = ['created_at']


class TestimonialSerializer(serializers.ModelSerializer):
    """Serializer for Testimonial model."""
    
    class Meta:
        model = Testimonial
        fields = [
            'id', 'author_name', 'author_title', 'author_image',
            'content', 'rating', 'created_at'
        ]
        read_only_fields = ['created_at']


class LeaderboardSerializer(serializers.ModelSerializer):
    """Serializer for Leaderboard Entry model."""
    
    class Meta:
        model = LeaderboardEntry
        fields = [
            'id', 'rank', 'user_name', 'avatar', 'monthly_return',
            'win_rate', 'total_trades', 'profit', 'created_at', 'updated_at'
        ]
        read_only_fields = ['created_at', 'updated_at']
