# -*- coding: utf-8 -*-
"""
Core App Serializers

This module contains common serializers and serializer utilities for the API.
"""

from rest_framework import serializers
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.conf import settings
import json

User = get_user_model()


class BaseSerializer(serializers.ModelSerializer):
    """
    Base serializer class with common functionality.
    """
    
    created_at = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M:%S')
    updated_at = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M:%S')
    
    class Meta:
        abstract = True
    
    def to_representation(self, instance):
        """
        Convert model instance to dictionary representation.
        """
        data = super().to_representation(instance)
        
        # Remove None values
        data = {key: value for key, value in data.items() if value is not None}
        
        return data


class HealthCheckSerializer(serializers.Serializer):
    """
    Serializer for health check responses.
    """
    
    status = serializers.CharField()
    timestamp = serializers.DateTimeField()
    version = serializers.CharField(required=False)
    uptime = serializers.CharField(required=False)
    
    # Database check
    database = serializers.DictField(required=False)
    
    # Cache check
    cache = serializers.DictField(required=False)
    
    # Redis check
    redis = serializers.DictField(required=False)
    
    # Celery check
    celery = serializers.DictField(required=False)
    
    # System resources
    system = serializers.DictField(required=False)
    
    def validate_status(self, value):
        """
        Validate status field.
        """
        valid_statuses = ['healthy', 'unhealthy', 'degraded']
        if value not in valid_statuses:
            raise serializers.ValidationError(f'Status must be one of: {valid_statuses}')
        return value


class SystemStatusSerializer(serializers.Serializer):
    """
    Serializer for system status responses.
    """
    
    status = serializers.CharField()
    timestamp = serializers.DateTimeField()
    version = serializers.CharField()
    environment = serializers.CharField()
    debug_mode = serializers.BooleanField()
    
    # System information
    system_info = serializers.DictField()
    
    # Database information
    database_info = serializers.DictField()
    
    # Cache information
    cache_info = serializers.DictField()
    
    # Application statistics
    app_stats = serializers.DictField()


class ErrorResponseSerializer(serializers.Serializer):
    """
    Serializer for error responses.
    """
    
    error = serializers.CharField()
    message = serializers.CharField()
    code = serializers.CharField(required=False)
    details = serializers.DictField(required=False)
    timestamp = serializers.DateTimeField(default=timezone.now)
    
    def validate_error(self, value):
        """
        Validate error field.
        """
        if not value or len(value.strip()) == 0:
            raise serializers.ValidationError('Error field cannot be empty.')
        return value.strip()


class PaginationSerializer(serializers.Serializer):
    """
    Serializer for pagination metadata.
    """
    
    count = serializers.IntegerField()
    next = serializers.URLField(allow_null=True, required=False)
    previous = serializers.URLField(allow_null=True, required=False)
    page_size = serializers.IntegerField()
    page_number = serializers.IntegerField()
    total_pages = serializers.IntegerField()
    
    def validate_count(self, value):
        """
        Validate count field.
        """
        if value < 0:
            raise serializers.ValidationError('Count cannot be negative.')
        return value
    
    def validate_page_size(self, value):
        """
        Validate page size field.
        """
        if value <= 0:
            raise serializers.ValidationError('Page size must be positive.')
        if value > 100:
            raise serializers.ValidationError('Page size cannot exceed 100.')
        return value


class ContactSerializer(serializers.Serializer):
    """
    Serializer for contact form submissions.
    """
    
    SUBJECT_CHOICES = [
        ('general', 'General Inquiry'),
        ('support', 'Technical Support'),
        ('billing', 'Billing Question'),
        ('feature', 'Feature Request'),
        ('bug', 'Bug Report'),
        ('other', 'Other'),
    ]
    
    name = serializers.CharField(max_length=100)
    email = serializers.EmailField()
    subject = serializers.ChoiceField(choices=SUBJECT_CHOICES)
    message = serializers.CharField(max_length=2000)
    
    def validate_name(self, value):
        """
        Validate name field.
        """
        if len(value.strip()) < 2:
            raise serializers.ValidationError('Name must be at least 2 characters long.')
        return value.strip()
    
    def validate_message(self, value):
        """
        Validate message field.
        """
        if len(value.strip()) < 10:
            raise serializers.ValidationError('Message must be at least 10 characters long.')
        return value.strip()


class FeedbackSerializer(serializers.Serializer):
    """
    Serializer for feedback submissions.
    """
    
    RATING_CHOICES = [(i, str(i)) for i in range(1, 6)]
    
    CATEGORY_CHOICES = [
        ('usability', 'Usability'),
        ('performance', 'Performance'),
        ('features', 'Features'),
        ('design', 'Design'),
        ('documentation', 'Documentation'),
        ('other', 'Other'),
    ]
    
    category = serializers.ChoiceField(choices=CATEGORY_CHOICES)
    rating = serializers.ChoiceField(choices=RATING_CHOICES)
    feedback = serializers.CharField(max_length=1000)
    email = serializers.EmailField(required=False, allow_blank=True)
    
    def validate_feedback(self, value):
        """
        Validate feedback field.
        """
        if len(value.strip()) < 5:
            raise serializers.ValidationError('Feedback must be at least 5 characters long.')
        return value.strip()


class SearchSerializer(serializers.Serializer):
    """
    Serializer for search requests.
    """
    
    SEARCH_TYPE_CHOICES = [
        ('all', 'All'),
        ('campaigns', 'Campaigns'),
        ('advertisers', 'Advertisers'),
        ('channels', 'Channels'),
        ('activities', 'Activities'),
    ]
    
    query = serializers.CharField(max_length=200)
    search_type = serializers.ChoiceField(
        choices=SEARCH_TYPE_CHOICES,
        default='all',
        required=False
    )
    page = serializers.IntegerField(default=1, min_value=1)
    page_size = serializers.IntegerField(default=20, min_value=1, max_value=100)
    
    def validate_query(self, value):
        """
        Validate search query.
        """
        query = value.strip()
        if len(query) < 2:
            raise serializers.ValidationError('Search query must be at least 2 characters long.')
        
        # Remove potentially harmful characters
        import re
        query = re.sub(r'[<>"\']', '', query)
        
        return query


class SearchResultSerializer(serializers.Serializer):
    """
    Serializer for search results.
    """
    
    id = serializers.IntegerField()
    title = serializers.CharField()
    description = serializers.CharField(required=False)
    type = serializers.CharField()
    url = serializers.URLField(required=False)
    relevance_score = serializers.FloatField(required=False)
    created_at = serializers.DateTimeField(required=False)
    updated_at = serializers.DateTimeField(required=False)


class ExportSerializer(serializers.Serializer):
    """
    Serializer for data export requests.
    """
    
    FORMAT_CHOICES = [
        ('csv', 'CSV'),
        ('xlsx', 'Excel'),
        ('pdf', 'PDF'),
        ('json', 'JSON'),
    ]
    
    format = serializers.ChoiceField(choices=FORMAT_CHOICES, default='csv')
    include_headers = serializers.BooleanField(default=True)
    date_format = serializers.CharField(default='%Y-%m-%d', max_length=50)
    filters = serializers.DictField(required=False)
    
    def validate_date_format(self, value):
        """
        Validate date format string.
        """
        try:
            # Test the format with a sample date
            test_date = timezone.now().date()
            test_date.strftime(value)
        except ValueError:
            raise serializers.ValidationError('Invalid date format string.')
        
        return value


class BulkActionSerializer(serializers.Serializer):
    """
    Serializer for bulk actions.
    """
    
    ACTION_CHOICES = [
        ('delete', 'Delete'),
        ('export', 'Export'),
        ('activate', 'Activate'),
        ('deactivate', 'Deactivate'),
    ]
    
    action = serializers.ChoiceField(choices=ACTION_CHOICES)
    item_ids = serializers.ListField(
        child=serializers.IntegerField(min_value=1),
        min_length=1
    )
    confirm = serializers.BooleanField(default=False)
    
    def validate(self, data):
        """
        Validate bulk action data.
        """
        action = data.get('action')
        confirm = data.get('confirm')
        
        # For destructive actions, require confirmation
        if action in ['delete'] and not confirm:
            raise serializers.ValidationError({
                'confirm': 'Confirmation is required for destructive actions.'
            })
        
        return data


class VersionSerializer(serializers.Serializer):
    """
    Serializer for version information.
    """
    
    version = serializers.CharField()
    build = serializers.CharField(required=False)
    commit = serializers.CharField(required=False)
    build_date = serializers.DateTimeField(required=False)
    environment = serializers.CharField()
    debug_mode = serializers.BooleanField()
    
    # API version information
    api_version = serializers.CharField(required=False)
    api_docs_url = serializers.URLField(required=False)
    
    # Dependencies
    dependencies = serializers.DictField(required=False)


class StatisticsSerializer(serializers.Serializer):
    """
    Serializer for application statistics.
    """
    
    total_users = serializers.IntegerField()
    active_users = serializers.IntegerField()
    total_campaigns = serializers.IntegerField()
    active_campaigns = serializers.IntegerField()
    total_advertisers = serializers.IntegerField()
    total_channels = serializers.IntegerField()
    
    # Performance metrics
    avg_response_time = serializers.FloatField(required=False)
    error_rate = serializers.FloatField(required=False)
    uptime_percentage = serializers.FloatField(required=False)
    
    # Resource usage
    memory_usage = serializers.DictField(required=False)
    cpu_usage = serializers.FloatField(required=False)
    disk_usage = serializers.DictField(required=False)
    
    # Time period
    period_start = serializers.DateTimeField(required=False)
    period_end = serializers.DateTimeField(required=False)


class LogEntrySerializer(serializers.Serializer):
    """
    Serializer for log entries.
    """
    
    LEVEL_CHOICES = [
        ('DEBUG', 'Debug'),
        ('INFO', 'Info'),
        ('WARNING', 'Warning'),
        ('ERROR', 'Error'),
        ('CRITICAL', 'Critical'),
    ]
    
    timestamp = serializers.DateTimeField()
    level = serializers.ChoiceField(choices=LEVEL_CHOICES)
    logger = serializers.CharField()
    message = serializers.CharField()
    module = serializers.CharField(required=False)
    function = serializers.CharField(required=False)
    line_number = serializers.IntegerField(required=False)
    
    # Additional context
    user_id = serializers.IntegerField(required=False)
    request_id = serializers.CharField(required=False)
    ip_address = serializers.IPAddressField(required=False)
    user_agent = serializers.CharField(required=False)
    
    # Exception information
    exception_type = serializers.CharField(required=False)
    exception_message = serializers.CharField(required=False)
    stack_trace = serializers.CharField(required=False)


class MetricsSerializer(serializers.Serializer):
    """
    Serializer for application metrics.
    """
    
    name = serializers.CharField()
    value = serializers.FloatField()
    unit = serializers.CharField(required=False)
    timestamp = serializers.DateTimeField()
    tags = serializers.DictField(required=False)
    
    def validate_value(self, value):
        """
        Validate metric value.
        """
        if value < 0:
            raise serializers.ValidationError('Metric value cannot be negative.')
        return value