"""
Worktable Service - API Serializers.
"""
from rest_framework import serializers

from .models import (
    TableDefinition,
    TableColumn,
    TableRecord,
    SavedFilter,
    CustomView,
    RecordAuditLog,
    FieldType,
    RecordStatus,
    AuditAction,
)
from .validators import SchemaValidator, DataValidator, ValidationError, MultiValidationError


# ============================================================================
# Column Serializers
# ============================================================================

class TableColumnSerializer(serializers.ModelSerializer):
    """Serializer for TableColumn model."""
    
    field_type_display = serializers.CharField(source='get_field_type_display', read_only=True)
    
    class Meta:
        model = TableColumn
        fields = [
            'id',
            'slug',
            'name',
            'field_type',
            'field_type_display',
            'config',
            'validation',
            'default_value',
            'order',
            'is_required',
            'is_unique',
            'is_searchable',
            'is_sortable',
            'is_filterable',
            'created_at',
            'updated_at',
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']
    
    def validate_slug(self, value):
        """Validate column slug."""
        table = self.context.get('table')
        if table:
            existing_slugs = set(table.columns.exclude(id=self.instance.id if self.instance else None).values_list('slug', flat=True))
            try:
                SchemaValidator.validate_column_slug(value, existing_slugs)
            except ValidationError as e:
                raise serializers.ValidationError(e.message)
        return value
    
    def validate(self, attrs):
        """Validate column config based on field type."""
        field_type = attrs.get('field_type', self.instance.field_type if self.instance else FieldType.TEXT)
        config = attrs.get('config', {})
        
        try:
            attrs['config'] = SchemaValidator.validate_column_config(field_type, config)
        except ValidationError as e:
            raise serializers.ValidationError({'config': e.message})
        
        return attrs


class TableColumnCreateSerializer(serializers.Serializer):
    """Serializer for creating columns (used in table creation)."""
    
    slug = serializers.SlugField(max_length=100, required=False)
    name = serializers.CharField(max_length=255)
    field_type = serializers.ChoiceField(choices=FieldType.choices, default=FieldType.TEXT)
    config = serializers.JSONField(required=False, default=dict)
    order = serializers.IntegerField(required=False)
    is_required = serializers.BooleanField(default=False)
    is_unique = serializers.BooleanField(default=False)
    is_searchable = serializers.BooleanField(default=True)
    is_sortable = serializers.BooleanField(default=True)
    is_filterable = serializers.BooleanField(default=True)
    show_in_list = serializers.BooleanField(default=True)
    show_in_detail = serializers.BooleanField(default=True)


class ColumnReorderSerializer(serializers.Serializer):
    """Serializer for column reordering."""
    
    orders = serializers.ListField(
        child=serializers.DictField(child=serializers.CharField()),
        help_text='List of {id, order} objects'
    )


# ============================================================================
# Table Serializers
# ============================================================================

class TableDefinitionListSerializer(serializers.ModelSerializer):
    """List serializer for TableDefinition - minimal fields."""
    
    column_count = serializers.IntegerField(read_only=True)
    record_count = serializers.IntegerField(read_only=True)
    
    class Meta:
        model = TableDefinition
        fields = [
            'id',
            'slug',
            'name',
            'description',
            'icon',
            'is_active',
            'column_count',
            'record_count',
            'order',
            'created_at',
            'updated_at',
        ]


class TableDefinitionSerializer(serializers.ModelSerializer):
    """Full serializer for TableDefinition."""
    
    columns = TableColumnSerializer(many=True, read_only=True)
    column_count = serializers.IntegerField(read_only=True)
    record_count = serializers.IntegerField(read_only=True)
    
    class Meta:
        model = TableDefinition
        fields = [
            'id',
            'slug',
            'name',
            'description',
            'icon',
            'settings',
            'is_active',
            'enable_audit',
            'enable_workflow',
            'columns',
            'column_count',
            'record_count',
            'order',
            'created_at',
            'updated_at',
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']


class TableDefinitionCreateSerializer(serializers.ModelSerializer):
    """Serializer for creating TableDefinition with columns."""
    
    columns = TableColumnCreateSerializer(many=True, required=False)
    
    class Meta:
        model = TableDefinition
        fields = [
            'slug',
            'name',
            'description',
            'icon',
            'settings',
            'enable_audit',
            'enable_workflow',
            'order',
            'columns',
        ]
    
    def create(self, validated_data):
        columns_data = validated_data.pop('columns', [])
        from .services import TableService, ColumnService
        
        table = TableService.create_table(
            tenant=validated_data.pop('tenant'),
            name=validated_data['name'],
            slug=validated_data.get('slug'),
            description=validated_data.get('description'),
            icon=validated_data.get('icon'),
            settings=validated_data.get('settings'),
        )
        
        # Update additional fields
        for field in ['enable_audit', 'enable_workflow', 'order']:
            if field in validated_data:
                setattr(table, field, validated_data[field])
        table.save()
        
        # Create columns
        if columns_data:
            ColumnService.bulk_create_columns(table, columns_data)
        
        return table


class TableStatsSerializer(serializers.Serializer):
    """Serializer for table statistics."""
    
    total_records = serializers.IntegerField()
    active_records = serializers.IntegerField()
    deleted_records = serializers.IntegerField()
    column_count = serializers.IntegerField()
    view_count = serializers.IntegerField()
    filter_count = serializers.IntegerField()


# ============================================================================
# Record Serializers
# ============================================================================

class TableRecordSerializer(serializers.ModelSerializer):
    """Serializer for TableRecord."""
    
    owner_name = serializers.SerializerMethodField()
    status_display = serializers.CharField(source='get_status_display', read_only=True)
    computed_fields = serializers.SerializerMethodField()
    
    class Meta:
        model = TableRecord
        fields = [
            'id',
            'table',
            'data',
            'owner',
            'owner_name',
            'status',
            'status_display',
            'version',
            'is_deleted',
            'deleted_at',
            'computed_fields',
            'created_at',
            'updated_at',
        ]
        read_only_fields = ['id', 'table', 'owner', 'version', 'is_deleted', 'deleted_at', 'created_at', 'updated_at']
    
    def get_owner_name(self, obj):
        if obj.owner:
            return obj.owner.get_full_name() or obj.owner.email
        return None
    
    def get_computed_fields(self, obj):
        """Get computed field values."""
        from .services import ComputedFieldService
        return ComputedFieldService.compute_all_fields(obj.table, obj)


class TableRecordListSerializer(serializers.ModelSerializer):
    """List serializer for TableRecord - optimized for lists."""
    
    owner_name = serializers.SerializerMethodField()
    status_display = serializers.CharField(source='get_status_display', read_only=True)
    
    class Meta:
        model = TableRecord
        fields = [
            'id',
            'data',
            'owner',
            'owner_name',
            'status',
            'status_display',
            'version',
            'created_at',
            'updated_at',
        ]
    
    def get_owner_name(self, obj):
        if obj.owner:
            return obj.owner.get_full_name() or obj.owner.email
        return None


class TableRecordCreateSerializer(serializers.Serializer):
    """Serializer for creating a record."""
    
    data = serializers.JSONField()
    status = serializers.ChoiceField(choices=RecordStatus.choices, default=RecordStatus.DRAFT)
    
    def validate_data(self, value):
        """Validate record data against table schema."""
        table = self.context.get('table')
        if not table:
            return value
        
        columns = list(table.columns.all())
        validator = DataValidator(columns)
        
        try:
            return validator.validate(value)
        except MultiValidationError as e:
            raise serializers.ValidationError(e.to_dict())
        except ValidationError as e:
            raise serializers.ValidationError({e.field or 'data': e.message})


class TableRecordUpdateSerializer(serializers.Serializer):
    """Serializer for updating a record."""
    
    data = serializers.JSONField()
    status = serializers.ChoiceField(choices=RecordStatus.choices, required=False)
    
    def validate_data(self, value):
        """Validate record data against table schema (partial)."""
        table = self.context.get('table')
        if not table:
            return value
        
        columns = list(table.columns.all())
        validator = DataValidator(columns)
        
        try:
            return validator.validate(value, partial=True)
        except MultiValidationError as e:
            raise serializers.ValidationError(e.to_dict())
        except ValidationError as e:
            raise serializers.ValidationError({e.field or 'data': e.message})


class BulkCreateSerializer(serializers.Serializer):
    """Serializer for bulk record creation."""
    
    records = serializers.ListField(
        child=serializers.JSONField(),
        min_length=1,
        max_length=1000,
        help_text='List of record data objects'
    )


class BulkUpdateSerializer(serializers.Serializer):
    """Serializer for bulk record updates."""
    
    updates = serializers.ListField(
        child=serializers.DictField(),
        min_length=1,
        max_length=1000,
        help_text='List of {id, data} objects'
    )


class BulkDeleteSerializer(serializers.Serializer):
    """Serializer for bulk record deletion."""
    
    ids = serializers.ListField(
        child=serializers.UUIDField(),
        min_length=1,
        max_length=1000,
        help_text='List of record IDs to delete'
    )
    hard_delete = serializers.BooleanField(default=False)


class BulkResultSerializer(serializers.Serializer):
    """Serializer for bulk operation results."""
    
    success_count = serializers.IntegerField()
    error_count = serializers.IntegerField()
    errors = serializers.ListField(child=serializers.DictField(), required=False)


# ============================================================================
# Filter & View Serializers
# ============================================================================

class SavedFilterSerializer(serializers.ModelSerializer):
    """Serializer for SavedFilter."""
    
    class Meta:
        model = SavedFilter
        fields = [
            'id',
            'name',
            'filters',
            'is_default',
            'is_shared',
            'order',
            'created_at',
        ]
        read_only_fields = ['id', 'created_at']


class SavedFilterCreateSerializer(serializers.Serializer):
    """Serializer for creating a saved filter."""
    
    name = serializers.CharField(max_length=255)
    filters = serializers.JSONField()
    is_default = serializers.BooleanField(default=False)
    is_shared = serializers.BooleanField(default=False)


class CustomViewSerializer(serializers.ModelSerializer):
    """Serializer for CustomView."""
    
    class Meta:
        model = CustomView
        fields = [
            'id',
            'name',
            'columns',
            'sort',
            'filters',
            'is_default',
            'is_shared',
            'order',
            'created_at',
        ]
        read_only_fields = ['id', 'created_at']


class CustomViewCreateSerializer(serializers.Serializer):
    """Serializer for creating a custom view."""
    
    name = serializers.CharField(max_length=255)
    columns = serializers.ListField(child=serializers.DictField(), required=False)
    sort = serializers.ListField(child=serializers.DictField(), required=False)
    filters = serializers.JSONField(required=False)
    is_default = serializers.BooleanField(default=False)
    is_shared = serializers.BooleanField(default=False)


# ============================================================================
# Audit Log Serializers
# ============================================================================

class RecordAuditLogSerializer(serializers.ModelSerializer):
    """Serializer for RecordAuditLog."""
    
    user_name = serializers.SerializerMethodField()
    action_display = serializers.CharField(source='get_action_display', read_only=True)
    
    class Meta:
        model = RecordAuditLog
        fields = [
            'id',
            'record_id',
            'user',
            'user_name',
            'action',
            'action_display',
            'changes',
            'metadata',
            'ip_address',
            'user_agent',
            'created_at',
        ]
    
    def get_user_name(self, obj):
        if obj.user:
            return obj.user.get_full_name() or obj.user.email
        return None


# ============================================================================
# Export/Import Serializers
# ============================================================================

class ExportSerializer(serializers.Serializer):
    """Serializer for export request."""
    
    format = serializers.ChoiceField(choices=['csv', 'json'], default='csv')
    columns = serializers.ListField(
        child=serializers.CharField(),
        required=False,
        help_text='List of column slugs to include (all if not specified)'
    )
    filters = serializers.JSONField(required=False)


class ImportSerializer(serializers.Serializer):
    """Serializer for import request."""
    
    file = serializers.FileField()
    format = serializers.ChoiceField(choices=['csv', 'json'], default='csv')
    column_mapping = serializers.JSONField(
        required=False,
        help_text='Mapping of file column names to table column slugs'
    )
