"""
DRF Serializers for Schedule App with Availability Validation
"""
from rest_framework import serializers
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError as DjangoValidationError
from .models import Resource, Event, Participant, Service, ResourceType, ScheduledTask, TaskExecutionLog, PluginTemplate, PluginInstallation, EventPlugin, GlobalEventPlugin, EmailTemplate
from .services import AvailabilityService
from smoothschedule.users.models import User


class ResourceTypeSerializer(serializers.ModelSerializer):
    """Serializer for custom resource types"""

    class Meta:
        model = ResourceType
        fields = ['id', 'name', 'description', 'category', 'is_default', 'icon_name', 'created_at', 'updated_at']
        read_only_fields = ['id', 'created_at', 'updated_at', 'is_default']

    def validate(self, attrs):
        # If updating, check if trying to modify is_default
        if self.instance and self.instance.is_default:
            if 'name' in attrs and attrs['name'] != self.instance.name:
                # Allow renaming default types
                pass
        return attrs

    def delete(self, instance):
        """Validate before deletion"""
        if instance.is_default:
            raise serializers.ValidationError("Cannot delete default resource types.")
        if instance.resources.exists():
            raise serializers.ValidationError(
                f"Cannot delete resource type '{instance.name}' because it is in use by {instance.resources.count()} resource(s)."
            )


class CustomerSerializer(serializers.ModelSerializer):
    """Serializer for Customer (User with role=CUSTOMER)"""
    name = serializers.SerializerMethodField()
    total_spend = serializers.SerializerMethodField()
    last_visit = serializers.SerializerMethodField()
    status = serializers.SerializerMethodField()
    avatar_url = serializers.SerializerMethodField()
    tags = serializers.SerializerMethodField()
    user_id = serializers.IntegerField(source='id', read_only=True)
    city = serializers.SerializerMethodField()
    state = serializers.SerializerMethodField()
    zip = serializers.SerializerMethodField()
    user_data = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = [
            'id', 'name', 'email', 'phone', 'city', 'state', 'zip',
            'total_spend', 'last_visit', 'status', 'avatar_url', 'tags',
            'user_id', 'user_data',
        ]
        read_only_fields = ['id', 'email']

    def get_name(self, obj):
        return obj.full_name

    def get_total_spend(self, obj):
        # TODO: Calculate from payments when implemented
        return 0

    def get_last_visit(self, obj):
        # TODO: Get from last appointment when implemented
        return None

    def get_status(self, obj):
        return 'Active' if obj.is_active else 'Inactive'

    def get_avatar_url(self, obj):
        return None  # TODO: Implement avatar

    def get_tags(self, obj):
        return []  # TODO: Implement customer tags

    def get_city(self, obj):
        return ''  # TODO: Add address fields to User model

    def get_state(self, obj):
        return ''

    def get_zip(self, obj):
        return ''

    def get_user_data(self, obj):
        """Return user data needed for masquerading"""
        return {
            'id': obj.id,
            'username': obj.username,
            'name': obj.full_name,
            'email': obj.email,
            'role': 'customer',
        }


class StaffSerializer(serializers.ModelSerializer):
    """Serializer for Staff members (Users with staff roles)"""
    name = serializers.SerializerMethodField()
    role = serializers.SerializerMethodField()
    can_invite_staff = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = [
            'id', 'username', 'name', 'email', 'phone', 'role',
            'is_active', 'permissions', 'can_invite_staff',
        ]
        read_only_fields = ['id', 'username', 'email', 'role', 'can_invite_staff']

    def get_name(self, obj):
        return obj.full_name

    def get_role(self, obj):
        # Map database roles to frontend roles
        role_mapping = {
            'TENANT_OWNER': 'owner',
            'TENANT_MANAGER': 'manager',
            'TENANT_STAFF': 'staff',
        }
        return role_mapping.get(obj.role, obj.role.lower())

    def get_can_invite_staff(self, obj):
        return obj.can_invite_staff()


class ServiceSerializer(serializers.ModelSerializer):
    """Serializer for Service model"""
    duration_minutes = serializers.IntegerField(source='duration', read_only=True)

    class Meta:
        model = Service
        fields = [
            'id', 'name', 'description', 'duration', 'duration_minutes',
            'price', 'display_order', 'photos', 'is_active', 'created_at', 'updated_at',
        ]
        read_only_fields = ['created_at', 'updated_at']


class ResourceSerializer(serializers.ModelSerializer):
    """Serializer for Resource model"""
    capacity_description = serializers.SerializerMethodField()
    user_id = serializers.IntegerField(required=False, allow_null=True)
    user_name = serializers.CharField(source='user.full_name', read_only=True, allow_null=True)

    class Meta:
        model = Resource
        fields = [
            'id', 'name', 'type', 'user_id', 'user_name',
            'description', 'max_concurrent_events',
            'buffer_duration', 'is_active', 'capacity_description',
            'saved_lane_count', 'created_at', 'updated_at',
        ]
        read_only_fields = ['created_at', 'updated_at']

    def get_capacity_description(self, obj):
        if obj.max_concurrent_events == 0:
            return "Unlimited capacity"
        elif obj.max_concurrent_events == 1:
            return "Exclusive use (1 at a time)"
        return f"Up to {obj.max_concurrent_events} concurrent events"

    def to_representation(self, instance):
        """Add user_id to the output"""
        ret = super().to_representation(instance)
        ret['user_id'] = instance.user_id
        return ret

    def create(self, validated_data):
        """Handle user_id when creating a resource"""
        user_id = validated_data.pop('user_id', None)
        if user_id:
            try:
                validated_data['user'] = User.objects.get(id=user_id)
            except User.DoesNotExist:
                pass
        return super().create(validated_data)

    def update(self, instance, validated_data):
        """Handle user_id when updating a resource"""
        user_id = validated_data.pop('user_id', None)
        if user_id is not None:
            if user_id:
                try:
                    validated_data['user'] = User.objects.get(id=user_id)
                except User.DoesNotExist:
                    pass
            else:
                validated_data['user'] = None
        return super().update(instance, validated_data)


class ParticipantSerializer(serializers.ModelSerializer):
    """Serializer for Participant model"""
    content_type_str = serializers.SerializerMethodField()
    participant_display = serializers.SerializerMethodField()
    
    class Meta:
        model = Participant
        fields = [
            'id', 'event', 'role', 'content_type', 'object_id',
            'content_type_str', 'participant_display', 'created_at',
        ]
        read_only_fields = ['created_at']
    
    def get_content_type_str(self, obj):
        return str(obj.content_type)
    
    def get_participant_display(self, obj):
        return str(obj.content_object) if obj.content_object else None


class EventSerializer(serializers.ModelSerializer):
    """
    Serializer for Event model with availability validation.

    CRITICAL: Validates resource availability before saving via AvailabilityService.

    Status mapping (frontend -> backend):
    - PENDING -> SCHEDULED
    - CONFIRMED -> SCHEDULED
    - CANCELLED -> CANCELED
    - NO_SHOW -> NOSHOW
    """
    # Status mapping: frontend value -> backend value
    STATUS_MAPPING = {
        'PENDING': 'SCHEDULED',
        'CONFIRMED': 'SCHEDULED',
        'CANCELLED': 'CANCELED',
        'NO_SHOW': 'NOSHOW',
    }

    # Reverse mapping for serialization: backend value -> frontend value
    STATUS_REVERSE_MAPPING = {
        'SCHEDULED': 'CONFIRMED',
        'CANCELED': 'CANCELLED',
        'NOSHOW': 'NO_SHOW',
    }

    participants = ParticipantSerializer(many=True, read_only=True)
    duration_minutes = serializers.SerializerMethodField()

    # Override status field to allow frontend values
    status = serializers.CharField(required=False)

    # Simplified fields for frontend compatibility
    resource_id = serializers.SerializerMethodField()
    customer_id = serializers.SerializerMethodField()
    service_id = serializers.SerializerMethodField()
    customer_name = serializers.SerializerMethodField()
    service_name = serializers.SerializerMethodField()
    is_paid = serializers.SerializerMethodField()

    # Write-only fields for creating participants
    resource_ids = serializers.ListField(
        child=serializers.IntegerField(),
        write_only=True,
        required=False,
        help_text="List of Resource IDs to assign"
    )
    staff_ids = serializers.ListField(
        child=serializers.IntegerField(),
        write_only=True,
        required=False,
        help_text="List of Staff (User) IDs to assign"
    )
    
    class Meta:
        model = Event
        fields = [
            'id', 'title', 'start_time', 'end_time', 'status', 'notes',
            'duration_minutes', 'participants', 'resource_ids', 'staff_ids',
            'resource_id', 'customer_id', 'service_id', 'customer_name', 'service_name', 'is_paid',
            'created_at', 'updated_at', 'created_by',
        ]
        read_only_fields = ['created_at', 'updated_at', 'created_by']

    def get_duration_minutes(self, obj):
        return int(obj.duration.total_seconds() / 60)

    def get_resource_id(self, obj):
        """Get first resource ID from participants"""
        resource_participant = obj.participants.filter(role='RESOURCE').first()
        return resource_participant.object_id if resource_participant else None

    def get_customer_id(self, obj):
        """Get customer ID from participants"""
        customer_participant = obj.participants.filter(role='CUSTOMER').first()
        return customer_participant.object_id if customer_participant else None

    def get_service_id(self, obj):
        """Get service ID - placeholder for now"""
        # TODO: Add service link to Event model or participants
        return 1

    def get_customer_name(self, obj):
        """Get customer name from participant"""
        customer_participant = obj.participants.filter(role='CUSTOMER').first()
        if customer_participant and customer_participant.content_object:
            user = customer_participant.content_object
            return user.full_name if hasattr(user, 'full_name') else str(user)
        # Fallback to title
        return obj.title.split(' - ')[0] if ' - ' in obj.title else obj.title

    def get_service_name(self, obj):
        """Get service name from title"""
        # Extract from title format "Customer Name - Service Name"
        if ' - ' in obj.title:
            return obj.title.split(' - ')[-1]
        return "Service"

    def get_is_paid(self, obj):
        """Check if event is paid"""
        return obj.status == 'PAID'

    def validate_status(self, value):
        """Map frontend status values to backend values"""
        if value in self.STATUS_MAPPING:
            return self.STATUS_MAPPING[value]
        # Accept backend values directly
        valid_backend_statuses = [s.value for s in Event.Status]
        if value in valid_backend_statuses:
            return value
        raise serializers.ValidationError(
            f'Invalid status "{value}". Valid values are: '
            f'{", ".join(list(self.STATUS_MAPPING.keys()) + valid_backend_statuses)}'
        )

    def to_representation(self, instance):
        """Map backend status values to frontend values when serializing"""
        data = super().to_representation(instance)
        if 'status' in data and data['status'] in self.STATUS_REVERSE_MAPPING:
            data['status'] = self.STATUS_REVERSE_MAPPING[data['status']]
        return data

    def validate(self, attrs):
        """
        Validate event timing and resource availability.

        Checks:
        1. end_time > start_time
        2. start_time not in past (for new events)
        3. Resource availability using AvailabilityService
        """
        # For partial updates, get existing values from instance if not provided
        start_time = attrs.get('start_time')
        end_time = attrs.get('end_time')
        resource_ids = attrs.get('resource_ids', [])

        # If this is a partial update, fill in missing values from existing instance
        if self.instance:
            if start_time is None:
                start_time = self.instance.start_time
            if end_time is None:
                end_time = self.instance.end_time

        # Skip validation if we still don't have both times (shouldn't happen for valid requests)
        if start_time is None or end_time is None:
            return attrs

        # Validation 1: End must be after start
        if end_time <= start_time:
            raise serializers.ValidationError({
                'end_time': 'End time must be after start time'
            })
        
        # Validation 2: No past events (only for new events)
        if not self.instance:
            from django.utils import timezone
            if start_time < timezone.now():
                raise serializers.ValidationError({
                    'start_time': 'Cannot create events in the past'
                })
        
        # Validation 3: Check resource availability
        # CRITICAL: This enforces concurrency limits
        event_id = self.instance.id if self.instance else None
        availability_errors = []
        
        for resource_id in resource_ids:
            try:
                resource = Resource.objects.get(id=resource_id, is_active=True)
            except Resource.DoesNotExist:
                availability_errors.append(f"Resource ID {resource_id} not found or inactive")
                continue
            
            # Call the availability service
            is_available, reason = AvailabilityService.check_availability(
                resource=resource,
                start_time=start_time,
                end_time=end_time,
                exclude_event_id=event_id
            )
            
            if not is_available:
                availability_errors.append(f"{resource.name}: {reason}")
        
        if availability_errors:
            raise serializers.ValidationError({
                'non_field_errors': availability_errors
            })
        
        return attrs
    
    def create(self, validated_data):
        """Create event and associated participants"""
        resource_ids = validated_data.pop('resource_ids', [])
        staff_ids = validated_data.pop('staff_ids', [])
        
        # Set created_by from request user (only if authenticated)
        request = self.context.get('request')
        if request and hasattr(request, 'user') and request.user.is_authenticated:
            validated_data['created_by'] = request.user
        else:
            validated_data['created_by'] = None  # TODO: Remove for production
        
        # Create the event
        event = Event.objects.create(**validated_data)
        
        # Create Resource participants
        resource_content_type = ContentType.objects.get_for_model(Resource)
        for resource_id in resource_ids:
            Participant.objects.create(
                event=event,
                content_type=resource_content_type,
                object_id=resource_id,
                role=Participant.Role.RESOURCE
            )
        
        # Create Staff participants
        from smoothschedule.users.models import User
        user_content_type = ContentType.objects.get_for_model(User)
        for staff_id in staff_ids:
            Participant.objects.create(
                event=event,
                content_type=user_content_type,
                object_id=staff_id,
                role=Participant.Role.STAFF
            )
        
        return event
    
    def update(self, instance, validated_data):
        """Update event. Participants managed separately."""
        validated_data.pop('resource_ids', None)
        validated_data.pop('staff_ids', None)
        
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        
        instance.save()
        return instance


class ScheduledTaskSerializer(serializers.ModelSerializer):
    """Serializer for ScheduledTask model"""

    created_by_name = serializers.SerializerMethodField()
    plugin_display_name = serializers.SerializerMethodField()

    class Meta:
        model = ScheduledTask
        fields = [
            'id',
            'name',
            'description',
            'plugin_name',
            'plugin_display_name',
            'plugin_config',
            'schedule_type',
            'cron_expression',
            'interval_minutes',
            'run_at',
            'status',
            'last_run_at',
            'last_run_status',
            'last_run_result',
            'next_run_at',
            'created_at',
            'updated_at',
            'created_by',
            'created_by_name',
            'celery_task_id',
        ]
        read_only_fields = [
            'id',
            'created_at',
            'updated_at',
            'last_run_at',
            'last_run_status',
            'last_run_result',
            'next_run_at',
            'created_by',
            'celery_task_id',
        ]

    def get_created_by_name(self, obj):
        """Get name of user who created the task"""
        if obj.created_by:
            return obj.created_by.get_full_name() or obj.created_by.username
        return None

    def get_plugin_display_name(self, obj):
        """Get display name of the plugin"""
        from .plugins import registry
        plugin_class = registry.get(obj.plugin_name)
        if plugin_class:
            return plugin_class.display_name
        return obj.plugin_name

    def validate(self, attrs):
        """Validate schedule configuration"""
        schedule_type = attrs.get('schedule_type')

        if schedule_type == ScheduledTask.ScheduleType.CRON:
            if not attrs.get('cron_expression'):
                raise serializers.ValidationError({
                    'cron_expression': 'Cron expression is required for CRON schedule type'
                })

        if schedule_type == ScheduledTask.ScheduleType.INTERVAL:
            if not attrs.get('interval_minutes'):
                raise serializers.ValidationError({
                    'interval_minutes': 'Interval minutes is required for INTERVAL schedule type'
                })

        if schedule_type == ScheduledTask.ScheduleType.ONE_TIME:
            if not attrs.get('run_at'):
                raise serializers.ValidationError({
                    'run_at': 'Run at datetime is required for ONE_TIME schedule type'
                })

        return attrs

    def validate_plugin_name(self, value):
        """Validate that the plugin exists"""
        from .plugins import registry
        if not registry.get(value):
            raise serializers.ValidationError(f"Plugin '{value}' not found")
        return value

    def validate_plugin_config(self, value):
        """Validate plugin configuration against schema"""
        if not isinstance(value, dict):
            raise serializers.ValidationError("Plugin config must be a dictionary")
        return value

    def create(self, validated_data):
        """Create scheduled task and calculate next run time"""
        task = super().create(validated_data)
        task.update_next_run_time()
        return task

    def update(self, instance, validated_data):
        """Update scheduled task and recalculate next run time"""
        task = super().update(instance, validated_data)
        task.update_next_run_time()
        return task


class TaskExecutionLogSerializer(serializers.ModelSerializer):
    """Serializer for TaskExecutionLog model"""

    scheduled_task_name = serializers.CharField(source='scheduled_task.name', read_only=True)
    plugin_name = serializers.CharField(source='scheduled_task.plugin_name', read_only=True)

    class Meta:
        model = TaskExecutionLog
        fields = [
            'id',
            'scheduled_task',
            'scheduled_task_name',
            'plugin_name',
            'started_at',
            'completed_at',
            'status',
            'result',
            'error_message',
            'execution_time_ms',
        ]
        read_only_fields = '__all__'


class PluginInfoSerializer(serializers.Serializer):
    """Serializer for plugin metadata"""

    name = serializers.CharField()
    display_name = serializers.CharField()
    description = serializers.CharField()
    category = serializers.CharField()
    config_schema = serializers.DictField()


class PluginTemplateSerializer(serializers.ModelSerializer):
    """Serializer for PluginTemplate model"""

    author_name = serializers.CharField(read_only=True)
    approved_by_name = serializers.SerializerMethodField()
    can_publish = serializers.SerializerMethodField()
    validation_errors = serializers.SerializerMethodField()

    class Meta:
        model = PluginTemplate
        fields = [
            'id', 'name', 'slug', 'description', 'short_description',
            'plugin_code', 'plugin_code_hash', 'template_variables', 'default_config',
            'visibility', 'category', 'tags',
            'author', 'author_name', 'version', 'license_type', 'logo_url',
            'is_approved', 'approved_by', 'approved_by_name', 'approved_at', 'rejection_reason',
            'install_count', 'rating_average', 'rating_count',
            'created_at', 'updated_at', 'published_at',
            'can_publish', 'validation_errors',
        ]
        read_only_fields = [
            'id', 'slug', 'plugin_code_hash', 'template_variables',
            'author', 'author_name', 'is_approved', 'approved_by', 'approved_by_name',
            'approved_at', 'rejection_reason', 'install_count', 'rating_average',
            'rating_count', 'created_at', 'updated_at', 'published_at',
        ]

    def get_approved_by_name(self, obj):
        """Get name of user who approved the plugin"""
        if obj.approved_by:
            return obj.approved_by.get_full_name() or obj.approved_by.username
        return None

    def get_can_publish(self, obj):
        """Check if plugin can be published to marketplace"""
        return obj.can_be_published()

    def get_validation_errors(self, obj):
        """Get validation errors for publishing"""
        from .safe_scripting import validate_plugin_whitelist
        validation = validate_plugin_whitelist(obj.plugin_code)
        if not validation['valid']:
            return validation['errors']
        return []

    def create(self, validated_data):
        """Set author from request user"""
        request = self.context.get('request')
        if request and hasattr(request, 'user'):
            validated_data['author'] = request.user
        return super().create(validated_data)

    def validate_plugin_code(self, value):
        """Validate plugin code and extract template variables"""
        if not value or not value.strip():
            raise serializers.ValidationError("Plugin code cannot be empty")

        # Extract template variables
        from .template_parser import TemplateVariableParser
        try:
            template_vars = TemplateVariableParser.extract_variables(value)
        except Exception as e:
            raise serializers.ValidationError(f"Failed to parse template variables: {str(e)}")

        return value


class PluginTemplateListSerializer(serializers.ModelSerializer):
    """Lightweight serializer for plugin template listing"""

    author_name = serializers.CharField(read_only=True)

    class Meta:
        model = PluginTemplate
        fields = [
            'id', 'name', 'slug', 'short_description', 'description',
            'visibility', 'category', 'tags',
            'author_name', 'version', 'license_type', 'logo_url', 'is_approved',
            'install_count', 'rating_average', 'rating_count',
            'created_at', 'updated_at', 'published_at',
        ]
        read_only_fields = fields  # All fields are read-only for list view


class PluginInstallationSerializer(serializers.ModelSerializer):
    """Serializer for PluginInstallation model"""

    template_name = serializers.CharField(source='template.name', read_only=True)
    template_slug = serializers.CharField(source='template.slug', read_only=True)
    template_description = serializers.CharField(source='template.description', read_only=True)
    category = serializers.CharField(source='template.category', read_only=True)
    version = serializers.CharField(source='template.version', read_only=True)
    author_name = serializers.CharField(source='template.author_name', read_only=True)
    logo_url = serializers.CharField(source='template.logo_url', read_only=True)
    template_variables = serializers.JSONField(source='template.template_variables', read_only=True)
    scheduled_task_name = serializers.CharField(source='scheduled_task.name', read_only=True)
    installed_by_name = serializers.SerializerMethodField()
    has_update = serializers.SerializerMethodField()

    class Meta:
        model = PluginInstallation
        fields = [
            'id', 'template', 'template_name', 'template_slug', 'template_description',
            'category', 'version', 'author_name', 'logo_url', 'template_variables',
            'scheduled_task', 'scheduled_task_name',
            'installed_by', 'installed_by_name', 'installed_at',
            'config_values', 'template_version_hash',
            'rating', 'review', 'reviewed_at',
            'has_update',
        ]
        read_only_fields = [
            'id', 'installed_by', 'installed_by_name', 'installed_at',
            'template_version_hash', 'reviewed_at',
        ]

    def get_installed_by_name(self, obj):
        """Get name of user who installed the plugin"""
        if obj.installed_by:
            return obj.installed_by.get_full_name() or obj.installed_by.username
        return None

    def get_has_update(self, obj):
        """Check if template has been updated"""
        return obj.has_update_available()

    def create(self, validated_data):
        """
        Create plugin installation.

        Installation makes the plugin available in "My Plugins".
        Scheduling is optional and done separately.
        """
        request = self.context.get('request')
        template = validated_data.get('template')

        # Set installed_by from request user
        if request and hasattr(request, 'user') and request.user.is_authenticated:
            validated_data['installed_by'] = request.user

        # Store template version hash for update detection
        if template:
            import hashlib
            validated_data['template_version_hash'] = hashlib.sha256(
                template.plugin_code.encode('utf-8')
            ).hexdigest()

        # Don't require scheduled_task on creation
        # It can be added later when user schedules the plugin
        validated_data.pop('scheduled_task', None)

        return super().create(validated_data)


class EventPluginSerializer(serializers.ModelSerializer):
    """
    Serializer for EventPlugin - attaching plugins to calendar events.

    Provides a visual-friendly representation of when plugins run:
    - trigger: 'before_start', 'at_start', 'after_start', 'after_end', 'on_complete', 'on_cancel'
    - offset_minutes: 0, 5, 10, 15, 30, 60 (for time-based triggers)
    """

    plugin_name = serializers.CharField(source='plugin_installation.template.name', read_only=True)
    plugin_description = serializers.CharField(source='plugin_installation.template.short_description', read_only=True)
    plugin_category = serializers.CharField(source='plugin_installation.template.category', read_only=True)
    plugin_logo_url = serializers.CharField(source='plugin_installation.template.logo_url', read_only=True)
    trigger_display = serializers.CharField(source='get_trigger_display', read_only=True)
    execution_time = serializers.SerializerMethodField()
    timing_description = serializers.SerializerMethodField()

    class Meta:
        model = EventPlugin
        fields = [
            'id',
            'event',
            'plugin_installation',
            'plugin_name',
            'plugin_description',
            'plugin_category',
            'plugin_logo_url',
            'trigger',
            'trigger_display',
            'offset_minutes',
            'timing_description',
            'execution_time',
            'is_active',
            'execution_order',
            'created_at',
        ]
        read_only_fields = ['id', 'created_at']

    def get_execution_time(self, obj):
        """Get the calculated execution time"""
        exec_time = obj.get_execution_time()
        return exec_time.isoformat() if exec_time else None

    def get_timing_description(self, obj):
        """
        Generate a human-readable description of when the plugin runs.
        Examples: "At start", "10 minutes before start", "30 minutes after end"
        """
        trigger = obj.trigger
        offset = obj.offset_minutes

        if trigger == EventPlugin.Trigger.BEFORE_START:
            if offset == 0:
                return "At start"
            return f"{offset} min before start"
        elif trigger == EventPlugin.Trigger.AT_START:
            if offset == 0:
                return "At start"
            return f"{offset} min after start"
        elif trigger == EventPlugin.Trigger.AFTER_START:
            if offset == 0:
                return "At start"
            return f"{offset} min after start"
        elif trigger == EventPlugin.Trigger.AFTER_END:
            if offset == 0:
                return "At end"
            return f"{offset} min after end"
        elif trigger == EventPlugin.Trigger.ON_COMPLETE:
            return "When completed"
        elif trigger == EventPlugin.Trigger.ON_CANCEL:
            return "When canceled"
        return "Unknown"

    def validate(self, attrs):
        """Validate that offset makes sense for the trigger type"""
        trigger = attrs.get('trigger', EventPlugin.Trigger.AT_START)
        offset = attrs.get('offset_minutes', 0)

        # Event-driven triggers don't use offset
        if trigger in [EventPlugin.Trigger.ON_COMPLETE, EventPlugin.Trigger.ON_CANCEL]:
            if offset != 0:
                attrs['offset_minutes'] = 0  # Auto-correct instead of error

        return attrs


class GlobalEventPluginSerializer(serializers.ModelSerializer):
    """
    Serializer for GlobalEventPlugin - rules for auto-attaching plugins to ALL events.

    When created, automatically applies to:
    1. All existing events
    2. All future events as they are created
    """

    plugin_name = serializers.CharField(source='plugin_installation.template.name', read_only=True)
    plugin_description = serializers.CharField(source='plugin_installation.template.short_description', read_only=True)
    plugin_category = serializers.CharField(source='plugin_installation.template.category', read_only=True)
    plugin_logo_url = serializers.CharField(source='plugin_installation.template.logo_url', read_only=True)
    trigger_display = serializers.CharField(source='get_trigger_display', read_only=True)
    timing_description = serializers.SerializerMethodField()
    events_count = serializers.SerializerMethodField()

    class Meta:
        model = GlobalEventPlugin
        fields = [
            'id',
            'plugin_installation',
            'plugin_name',
            'plugin_description',
            'plugin_category',
            'plugin_logo_url',
            'trigger',
            'trigger_display',
            'offset_minutes',
            'timing_description',
            'is_active',
            'apply_to_existing',
            'execution_order',
            'events_count',
            'created_at',
            'updated_at',
            'created_by',
        ]
        read_only_fields = ['id', 'created_at', 'updated_at', 'created_by']

    def get_timing_description(self, obj):
        """Generate a human-readable description of when the plugin runs."""
        trigger = obj.trigger
        offset = obj.offset_minutes

        if trigger == 'before_start':
            if offset == 0:
                return "At start"
            return f"{offset} min before start"
        elif trigger == 'at_start':
            if offset == 0:
                return "At start"
            return f"{offset} min after start"
        elif trigger == 'after_start':
            if offset == 0:
                return "At start"
            return f"{offset} min after start"
        elif trigger == 'after_end':
            if offset == 0:
                return "At end"
            return f"{offset} min after end"
        elif trigger == 'on_complete':
            return "When completed"
        elif trigger == 'on_cancel':
            return "When canceled"
        return "Unknown"

    def get_events_count(self, obj):
        """Get the count of events this rule applies to."""
        return EventPlugin.objects.filter(
            plugin_installation=obj.plugin_installation,
            trigger=obj.trigger,
            offset_minutes=obj.offset_minutes,
        ).count()

    def validate(self, attrs):
        """Validate the global event plugin configuration."""
        trigger = attrs.get('trigger', 'at_start')
        offset = attrs.get('offset_minutes', 0)

        # Event-driven triggers don't use offset
        if trigger in ['on_complete', 'on_cancel']:
            if offset != 0:
                attrs['offset_minutes'] = 0

        return attrs

    def create(self, validated_data):
        """Create the global rule and apply to existing events."""
        # Set the created_by from request context
        request = self.context.get('request')
        if request and hasattr(request, 'user'):
            validated_data['created_by'] = request.user

        return super().create(validated_data)


class EmailTemplateSerializer(serializers.ModelSerializer):
    """Full serializer for EmailTemplate CRUD operations"""

    created_by_name = serializers.SerializerMethodField()

    class Meta:
        model = EmailTemplate
        fields = [
            'id', 'name', 'description', 'subject',
            'html_content', 'text_content', 'scope',
            'is_default', 'category', 'preview_context',
            'created_by', 'created_by_name',
            'created_at', 'updated_at',
        ]
        read_only_fields = ['created_at', 'updated_at', 'created_by', 'created_by_name']

    def get_created_by_name(self, obj):
        """Get the name of the user who created the template"""
        if obj.created_by:
            return obj.created_by.full_name or obj.created_by.username
        return None

    def validate(self, attrs):
        """Validate template content"""
        html = attrs.get('html_content', '')
        text = attrs.get('text_content', '')

        # At least one content type is required
        if not html and not text:
            raise serializers.ValidationError(
                "At least HTML or text content is required"
            )

        return attrs

    def create(self, validated_data):
        """Set created_by from request context"""
        request = self.context.get('request')
        if request and hasattr(request, 'user') and request.user.is_authenticated:
            validated_data['created_by'] = request.user
        return super().create(validated_data)


class EmailTemplateListSerializer(serializers.ModelSerializer):
    """Lightweight serializer for email template dropdowns and listings"""

    class Meta:
        model = EmailTemplate
        fields = ['id', 'name', 'description', 'category', 'scope', 'updated_at']
        read_only_fields = fields


class EmailTemplatePreviewSerializer(serializers.Serializer):
    """Serializer for email template preview endpoint"""

    subject = serializers.CharField()
    html_content = serializers.CharField(allow_blank=True, required=False, default='')
    text_content = serializers.CharField(allow_blank=True, required=False, default='')
    context = serializers.DictField(required=False, default=dict)