"""
Stateflow 序列化器
"""
from rest_framework import serializers
from django.db import transaction
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from stateflow import models


class StateParameterSerializer(serializers.ModelSerializer):
    """状态参数序列化器"""
    attachment_url = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = models.StateParameter
        fields = ['id', 'key', 'value', 'attachment', 'attachment_url', 'description', 'is_required', 'is_image_path']
        read_only_fields = ['id', 'attachment_url']
    
    def get_attachment_url(self, obj):
        """获取附件的完整 URL"""
        if obj.attachment:
            request = self.context.get('request')
            if request:
                return request.build_absolute_uri(obj.attachment.url)
            return obj.attachment.url
        return None


class StateListSerializer(serializers.ModelSerializer):
    """状态列表序列化器（不包含参数）"""
    
    class Meta:
        model = models.State
        fields = ['id', 'name', 'description', 'created_at', 'updated_at']
        read_only_fields = ['id', 'created_at', 'updated_at']


class StateDetailSerializer(serializers.ModelSerializer):
    """状态详情序列化器（包含参数）"""
    parameters = StateParameterSerializer(many=True, read_only=True)
    
    class Meta:
        model = models.State
        fields = ['id', 'name', 'description', 'parameters', 'created_at', 'updated_at']
        read_only_fields = ['id', 'created_at', 'updated_at']


class StateCreateUpdateSerializer(serializers.ModelSerializer):
    """状态创建/更新序列化器"""
    parameter_ids = serializers.ListField(
        child=serializers.IntegerField(),
        required=False,
        write_only=True,
        help_text="参数ID列表"
    )
    parameters = StateParameterSerializer(many=True, read_only=True)
    
    class Meta:
        model = models.State
        fields = ['name', 'description', 'parameter_ids', 'parameters']
    
    def validate_parameter_ids(self, value):
        """验证参数ID是否存在"""
        if value:
            existing_ids = set(models.StateParameter.objects.filter(id__in=value).values_list('id', flat=True))
            invalid_ids = set(value) - existing_ids
            if invalid_ids:
                raise serializers.ValidationError(f"参数ID不存在: {invalid_ids}")
        return value
    
    @transaction.atomic
    def create(self, validated_data):
        parameter_ids = validated_data.pop('parameter_ids', [])
        state = models.State.objects.create(**validated_data)
        
        # 关联参数（多对多）
        if parameter_ids:
            state.parameters.set(parameter_ids)
        
        return state
    
    @transaction.atomic
    def update(self, instance, validated_data):
        parameter_ids = validated_data.pop('parameter_ids', None)
        
        # 更新基本字段
        instance.name = validated_data.get('name', instance.name)
        instance.description = validated_data.get('description', instance.description)
        instance.save()
        
        # 如果提供了参数ID列表，更新关联
        if parameter_ids is not None:
            instance.parameters.set(parameter_ids)
        
        return instance


# Process 序列化器

class ProcessNodeSerializer(serializers.ModelSerializer):
    """流程节点序列化器"""
    state_id = serializers.IntegerField(source='state.id', read_only=True)
    state_name = serializers.CharField(source='state.name', read_only=True)
    
    class Meta:
        model = models.ProcessNode
        fields = ['id', 'state_id', 'state_name', 'order']
        read_only_fields = ['id']


class ProcessNodeCreateSerializer(serializers.Serializer):
    """流程节点创建序列化器"""
    state_id = serializers.IntegerField(help_text="状态ID")
    order = serializers.IntegerField(help_text="排序号", min_value=0)
    
    def validate_state_id(self, value):
        """验证状态是否存在"""
        try:
            models.State.objects.get(id=value)
        except models.State.DoesNotExist:
            raise serializers.ValidationError(f"状态ID {value} 不存在")
        return value


class ProcessListSerializer(serializers.ModelSerializer):
    """流程列表序列化器（不包含节点）"""
    node_count = serializers.IntegerField(read_only=True, help_text="节点数量")
    
    class Meta:
        model = models.Process
        fields = ['id', 'name', 'description', 'node_count', 'created_at', 'updated_at']
        read_only_fields = ['id', 'created_at', 'updated_at']


class ProcessDetailSerializer(serializers.ModelSerializer):
    """流程详情序列化器（包含节点）"""
    nodes = ProcessNodeSerializer(source='process_nodes', many=True, read_only=True)
    
    class Meta:
        model = models.Process
        fields = ['id', 'name', 'description', 'nodes', 'created_at', 'updated_at']
        read_only_fields = ['id', 'created_at', 'updated_at']


class ProcessCreateUpdateSerializer(serializers.ModelSerializer):
    """流程创建/更新序列化器"""
    nodes = ProcessNodeCreateSerializer(many=True, required=False, help_text="流程节点列表")
    
    class Meta:
        model = models.Process
        fields = ['name', 'description', 'nodes']
    
    @transaction.atomic
    def create(self, validated_data):
        nodes_data = validated_data.pop('nodes', [])
        process = models.Process.objects.create(**validated_data)
        
        # 创建节点
        for node_data in nodes_data:
            models.ProcessNode.objects.create(
                process=process,
                state_id=node_data['state_id'],
                order=node_data['order']
            )
        
        return process
    
    @transaction.atomic
    def update(self, instance, validated_data):
        nodes_data = validated_data.pop('nodes', None)
        
        # 更新基本字段
        instance.name = validated_data.get('name', instance.name)
        instance.description = validated_data.get('description', instance.description)
        instance.save()
        
        # 如果提供了节点数据，更新节点
        if nodes_data is not None:
            # 删除旧节点
            instance.process_nodes.all().delete()
            # 创建新节点
            for node_data in nodes_data:
                models.ProcessNode.objects.create(
                    process=instance,
                    state_id=node_data['state_id'],
                    order=node_data['order']
                )
        
        return instance


# BusinessObject 序列化器

class StateLogParameterRecordSerializer(serializers.ModelSerializer):
    """状态流转参数记录序列化器"""
    
    class Meta:
        model = models.StateLogParameterRecord
        fields = ['id', 'state_log', 'parameters', 'created_at', 'remark']
        read_only_fields = ['id', 'created_at']


class StateFlowRecordSerializer(serializers.ModelSerializer):
    """状态流转记录序列化器（只读）"""
    state_name = serializers.CharField(source='state.name', read_only=True)
    completed_by_username = serializers.CharField(source='completed_by.username', read_only=True)
    
    class Meta:
        model = models.StateFlowRecord
        fields = [
            'id', 'state', 'state_name', 'completed_at', 
            'completed_by', 'completed_by_username',
            'is_cancelled', 'cancelled_at'
        ]
        read_only_fields = ['id', 'completed_at', 'is_cancelled', 'cancelled_at']


class StateFlowRecordWithParametersSerializer(serializers.ModelSerializer):
    """状态流转记录序列化器（包含参数摘要）"""
    state_name = serializers.CharField(source='state.name', read_only=True)
    completed_by_username = serializers.CharField(source='completed_by.username', read_only=True)
    parameters_summary = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = models.StateFlowRecord
        fields = [
            'id', 'state', 'state_name', 'completed_at', 
            'completed_by', 'completed_by_username',
            'is_cancelled', 'cancelled_at',
            'parameters_summary'
        ]
        read_only_fields = ['id', 'completed_at', 'is_cancelled', 'cancelled_at']
    
    def get_parameters_summary(self, obj):
        """获取参数摘要，包含已撤销状态的参数"""
        return obj.get_all_parameters_summary(include_cancelled=True)


class BusinessObjectListSerializer(serializers.ModelSerializer):
    """业务对象列表序列化器"""
    process_name = serializers.CharField(source='process.name', read_only=True)
    current_state_name = serializers.SerializerMethodField()
    overall_status = serializers.SerializerMethodField()
    progress_percentage = serializers.SerializerMethodField()
    
    # 关联对象信息
    content_type_name = serializers.SerializerMethodField()
    
    class Meta:
        model = models.BusinessObject
        fields = [
            'id', 'name', 'process', 'process_name', 
            'current_state_name', 'overall_status', 'progress_percentage',
            'content_type', 'object_id', 'content_type_name',
            'description', 'created_at', 'updated_at'
        ]
    
    def get_current_state_name(self, obj):
        from . import services
        state = services.get_business_object_current_state(obj)
        return state.name if state else None
    
    def get_overall_status(self, obj):
        from . import services
        return services.get_overall_status(obj)
    
    def get_progress_percentage(self, obj):
        from . import services
        return round(services.get_progress_percentage(obj), 2)
    
    def get_content_type_name(self, obj):
        if obj.content_type:
            return f"{obj.content_type.app_label}.{obj.content_type.model}"
        return None


class BusinessObjectDetailSerializer(serializers.ModelSerializer):
    """业务对象详情序列化器"""
    process_detail = ProcessDetailSerializer(source='process', read_only=True)
    current_state = serializers.SerializerMethodField()
    overall_status = serializers.SerializerMethodField()
    progress_percentage = serializers.SerializerMethodField()
    timeline = serializers.SerializerMethodField()
    state_logs = StateFlowRecordSerializer(many=True, read_only=True)
    
    # 关联对象信息
    content_type_name = serializers.SerializerMethodField()
    
    class Meta:
        model = models.BusinessObject
        fields = [
            'id', 'name', 'process', 'process_detail',
            'current_state', 'overall_status', 'progress_percentage',
            'timeline', 'state_logs',
            'content_type', 'object_id', 'content_type_name',
            'description', 'created_at', 'updated_at'
        ]
    
    def get_current_state(self, obj):
        from . import services
        state = services.get_business_object_current_state(obj)
        if state:
            return StateListSerializer(state).data
        return None
    
    def get_overall_status(self, obj):
        from . import services
        return services.get_overall_status(obj)
    
    def get_progress_percentage(self, obj):
        from . import services
        return round(services.get_progress_percentage(obj), 2)
    
    def get_timeline(self, obj):
        from . import services
        timeline = services.get_business_object_state_timeline(obj)
        return [
            {
                'state': StateListSerializer(item['state']).data,
                'status': item['status'],
                'order': item['order'],
                'completed_at': item['completed_at'],
                'completed_by': item['completed_by'].username if item['completed_by'] else None,
                'cancelled_at': item['cancelled_at'],
                'is_cancelled': item['is_cancelled'],
            }
            for item in timeline
        ]
    
    def get_content_type_name(self, obj):
        if obj.content_type:
            return f"{obj.content_type.app_label}.{obj.content_type.model}"
        return None


class BusinessObjectCreateUpdateSerializer(serializers.ModelSerializer):
    """业务对象创建/更新序列化器"""
    
    # 支持通过 app_label.model 字符串指定 content_type
    content_type_str = serializers.CharField(
        write_only=True, 
        required=False, 
        allow_null=True,
        help_text="格式: app_label.model, 例如: basic_info.order"
    )
    
    class Meta:
        model = models.BusinessObject
        fields = [
            'name', 'process', 'description',
            'content_type', 'object_id', 'content_type_str'
        ]
        extra_kwargs = {
            'content_type': {'required': False, 'allow_null': True},
            'object_id': {'required': False, 'allow_null': True},
        }
    
    def validate(self, attrs):
        """
        业务约束：BusinessObject 必须绑定到一个“真实业务对象”。

        背景：
        - DB 允许 content_type/object_id 为空仅为历史兼容；
        - 但业务逻辑要求 BusinessObject 可通过 (content_type, object_id) 追溯到被追踪对象；
          否则整个流程实例将失去意义，并可能导致下游逻辑崩溃。
        """
        content_type = attrs.get('content_type')
        content_type_str = attrs.get('content_type_str')
        object_id = attrs.get('object_id')
        
        # 如果提供了 content_type_str，解析并设置 content_type
        if content_type_str:
            try:
                app_label, model = content_type_str.split('.')
                content_type = ContentType.objects.get(app_label=app_label, model=model)
                attrs['content_type'] = content_type
            except (ValueError, ContentType.DoesNotExist):
                raise serializers.ValidationError({
                    'content_type_str': f'无效的 content_type 格式: {content_type_str}'
                })

        # 以“最终值”做校验：partial_update 未传字段时要以 instance 的现有值为准
        if self.instance is not None:
            if 'content_type' not in attrs:
                content_type = self.instance.content_type
            if 'object_id' not in attrs:
                object_id = self.instance.object_id

        # 强制绑定：content_type/object_id 均不可为空
        if content_type is None or object_id is None:
            raise serializers.ValidationError({
                'detail': 'BusinessObject 必须绑定关联对象（content_type 与 object_id 均为必填且不可为空）'
            })

        # 强制要求绑定对象存在（避免产生“不可追溯”的悬空绑定）
        try:
            content_type.get_object_for_this_type(pk=object_id)
        except ObjectDoesNotExist:
            raise serializers.ValidationError({
                'object_id': f'关联对象不存在：{content_type.app_label}.{content_type.model} #{object_id}'
            })
        
        # 移除临时字段
        attrs.pop('content_type_str', None)
        
        return attrs
    
    @transaction.atomic
    def create(self, validated_data):
        return models.BusinessObject.objects.create(**validated_data)
    
    @transaction.atomic
    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        return instance
