"""
Printing API 序列化器
"""
from rest_framework import serializers

from api_v1.models import UploadedFile
from api_v1.utils.media import build_public_media_url
from printing import models
from .services import PrintingOrderService, PrintingJobService
from basic_info.models import Customer, Employee


def _build_absolute_media_url(url: str | None, request):
    return build_public_media_url(url, request=request)


def _serialize_plate_images(raw_value, request):
    if not raw_value:
        return []
    serialized = []
    if isinstance(raw_value, list):
        iterable = raw_value
    elif isinstance(raw_value, dict):
        iterable = [raw_value]
    elif isinstance(raw_value, str):
        iterable = [{'url': raw_value}]
    else:
        iterable = []

    for entry in iterable:
        if isinstance(entry, str):
            data = {'url': entry}
        elif isinstance(entry, dict):
            data = dict(entry)
        else:
            continue
        url = data.get('url') or data.get('path')
        data['url'] = _build_absolute_media_url(url, request)
        if 'path' not in data and isinstance(url, str):
            data['path'] = url
        serialized.append(data)
    return serialized


def _build_plate_image_payload(items, request_user):
    if items is None:
        return None
    if not items:
        return []
    file_ids = [item['file_id'] for item in items if item.get('file_id') is not None]
    if not file_ids:
        return []

    queryset = UploadedFile.objects.filter(id__in=file_ids, is_deleted=False)
    if request_user and request_user.is_authenticated:
        queryset = queryset.filter(owner=request_user)

    files_map = {file.id: file for file in queryset}
    missing = [str(fid) for fid in file_ids if fid not in files_map]
    if missing:
        raise serializers.ValidationError({'plate_image': f'以下文件不存在或已删除: {", ".join(missing)}'})

    payload = []
    for item in items:
        file = files_map[item['file_id']]
        name = item.get('name') or file.original_filename or file.path.name
        payload.append({
            'file_id': file.id,
            'name': name,
            'path': file.path.name,
            'url': file.file_url,
            'size': file.file_size,
            'content_type': file.content_type,
            'uploaded_at': file.created_at.isoformat(),
        })
    return payload


class PlateImageInputSerializer(serializers.Serializer):
    file_id = serializers.IntegerField(min_value=1, help_text='上传文件的 ID')
    name = serializers.CharField(
        required=False,
        allow_blank=True,
        allow_null=True,
        help_text='可选的图片名称，默认使用文件原始名称'
    )


class PrintingOrderListSerializer(serializers.ModelSerializer):
    """印染订单列表序列化器"""
    customer_name = serializers.CharField(source='customer.name', read_only=True)
    customer_phone = serializers.CharField(source='customer.mobile', read_only=True)
    process_name = serializers.CharField(source='process.name', read_only=True)
    progress = serializers.IntegerField(read_only=True)
    
    class Meta:
        model = models.PrintingOrder
        fields = [
            'id', 'human_id', 'customer', 'customer_name', 'customer_phone',
            'fabric', 'width', 'is_urgent', 'area', 'address', 'curve',
            'is_fabric_received', 'outgoing_date', 'is_invalid', 'new_curve',
            'process', 'process_name', 'progress', 'position', 'print_count',
            'created_at', 'updated_at',
        ]
        read_only_fields = ['id', 'human_id', 'created_at', 'updated_at', 'progress', 'print_count']


class PrintingOrderDetailSerializer(serializers.ModelSerializer):
    """印染订单详情序列化器"""
    customer_name = serializers.CharField(source='customer.name', read_only=True)
    customer_phone = serializers.CharField(source='customer.mobile', read_only=True)
    customer_area = serializers.CharField(source='customer.area', read_only=True)
    process_name = serializers.CharField(source='process.name', read_only=True)
    progress = serializers.IntegerField(read_only=True)
    
    class Meta:
        model = models.PrintingOrder
        fields = [
            'id', 'human_id', 'customer', 'customer_name', 'customer_phone', 'customer_area',
            'fabric', 'width', 'is_urgent', 'area', 'address', 'fabric_source',
            'is_fabric_received', 'craft', 'description', 'outgoing_date',
            'curve', 'new_curve', 'position',
            'printing_warn', 'rolling_warn', 'production_warn',
            'is_invalid', 'process', 'process_name', 'progress', 'print_count',
            'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'human_id', 'created_at', 'updated_at', 'progress', 'print_count']


class PrintingOrderCreateUpdateSerializer(serializers.ModelSerializer):
    """印染订单创建/更新序列化器"""
    
    class Meta:
        model = models.PrintingOrder
        fields = [
            'id', 'customer', 'fabric', 'width', 'is_urgent', 'area', 'address',
            'fabric_source', 'is_fabric_received', 'craft', 'description',
            'outgoing_date', 'curve', 'new_curve', 'position',
            'printing_warn', 'rolling_warn', 'production_warn', 'is_invalid',
            'process'
        ]
        read_only_fields = ['id']
    
    def validate_customer(self, value):
        """验证客户是否存在"""
        if not value:
            raise serializers.ValidationError("客户不能为空")
        return value
    
    def validate(self, attrs):
        """验证流程修改权限"""
        # 更新时验证 process 修改权限
        if self.instance and 'process' in attrs:
            new_process = attrs['process']
            old_process = self.instance.process
            
            if new_process != old_process:
                if not PrintingOrderService.can_change_process(self.instance):
                    raise serializers.ValidationError({
                        'process': '存在已开始的印染任务，无法修改流程'
                    })
        
        return attrs
    
    def create(self, validated_data):
        """创建订单，使用 service 层"""
        user = self.context['request'].user
        return PrintingOrderService.create_printing_order(validated_data, user)
    
    def update(self, instance, validated_data):
        """更新订单，使用 service 层"""
        user = self.context['request'].user
        success, message, updated_instance = PrintingOrderService.update_printing_order(
            instance, validated_data, user
        )
        if not success:
            raise serializers.ValidationError(message)
        return updated_instance


class PrintingJobListSerializer(serializers.ModelSerializer):
    """印染款式明细列表序列化器"""
    printing_order_id = serializers.CharField(source='printing_order.human_id', read_only=True)
    product_name = serializers.CharField(source='product.name', read_only=True)
    status = serializers.CharField(read_only=True)
    work_state_display = serializers.SerializerMethodField()
    is_completed = serializers.BooleanField(read_only=True)
    business_object_id = serializers.SerializerMethodField()
    batch_advance_records = serializers.SerializerMethodField()
    
    class Meta:
        model = models.PrintingJob
        fields = [
            'id', 'printing_order', 'printing_order_id', 'product', 'product_name',
            'quantity', 'unit', 'size', 'pieces', 'description',
            'work_state', 'work_state_display',
            'status', 'is_completed', 'business_object_id',
            'batch_advance_records',
            'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at', 'status', 'is_completed', 'business_object_id']
    
    def get_business_object_id(self, obj):
        """安全地获取 business_object_id"""
        return obj.business_object.id if obj.business_object else None

    def get_work_state_display(self, obj):
        return obj.get_work_state_display()

    def get_batch_advance_records(self, obj):
        """
        批量推进记录（稳定输出 key）
        
        - 如果没有批量记录：返回 []
        - 仅返回与该 job 相关的批量推进审计记录（按 created_at 倒序）
        """
        # 注意：这里不要链式调用 select_related/order_by，否则会绕开 viewset 的 prefetch 缓存，导致 N+1 查询。
        records = list(obj.batch_advance_records.all())
        return PrintingJobBatchAdvanceRecordSerializer(records, many=True).data


class PrintingJobDetailSerializer(serializers.ModelSerializer):
    """印染款式明细详情序列化器"""
    printing_order_id = serializers.CharField(source='printing_order.human_id', read_only=True)
    product_name = serializers.CharField(source='product.name', read_only=True)
    product_code = serializers.CharField(source='product.human_id', read_only=True)
    status = serializers.CharField(read_only=True)
    status_id = serializers.IntegerField(read_only=True)
    work_state_display = serializers.SerializerMethodField()
    is_completed = serializers.BooleanField(read_only=True)
    has_started = serializers.BooleanField(read_only=True)
    business_object_id = serializers.SerializerMethodField()
    batch_advance_records = serializers.SerializerMethodField()
    
    class Meta:
        model = models.PrintingJob
        fields = [
            'id', 'printing_order', 'printing_order_id', 'product', 'product_name', 'product_code',
            'quantity', 'unit', 'size', 'pieces', 'description',
            'work_state', 'work_state_display',
            'status', 'status_id', 'is_completed', 'has_started', 'business_object_id',
            'batch_advance_records',
            'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'created_at', 'updated_at', 
            'status', 'status_id', 'is_completed', 'has_started', 'business_object_id'
        ]
    
    def get_business_object_id(self, obj):
        """安全地获取 business_object_id"""
        return obj.business_object.id if obj.business_object else None

    def get_work_state_display(self, obj):
        return obj.get_work_state_display()

    def get_batch_advance_records(self, obj):
        """见 list serializer，同样稳定输出 key"""
        records = list(obj.batch_advance_records.all())
        return PrintingJobBatchAdvanceRecordSerializer(records, many=True).data


class PrintingJobCreateUpdateSerializer(serializers.ModelSerializer):
    """印染款式明细创建/更新序列化器"""
    batch_advance_records = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = models.PrintingJob
        fields = [
            'id', 'printing_order', 'product', 'quantity', 'unit', 'size', 'pieces', 'description',
            'work_state',
            'batch_advance_records',
        ]
        read_only_fields = ['id']
        extra_kwargs = {
            'size': {'required': False, 'allow_null': True, 'allow_blank': True},
            'pieces': {'required': False, 'allow_null': True},
            'description': {'required': False, 'allow_null': True, 'allow_blank': True},
            'work_state': {'required': False},
        }
    
    def validate_printing_order(self, value):
        """验证印染订单是否存在"""
        if not value:
            raise serializers.ValidationError("印染订单不能为空")
        return value
    
    def validate_product(self, value):
        """验证产品是否存在"""
        if not value:
            raise serializers.ValidationError("产品不能为空")
        return value
    
    def validate_quantity(self, value):
        """验证数量"""
        if value <= 0:
            raise serializers.ValidationError("数量必须大于0")
        return value
    
    def create(self, validated_data):
        """创建任务，使用 service 层"""
        user = self.context['request'].user
        return PrintingJobService.create_printing_job(validated_data, user)
    
    def update(self, instance, validated_data):
        """更新任务，使用 service 层"""
        user = self.context['request'].user
        success, message, updated_instance = PrintingJobService.update_printing_job(
            instance, validated_data, user
        )
        if not success:
            raise serializers.ValidationError(message)
        return updated_instance

    def get_batch_advance_records(self, obj):
        """创建/更新接口也稳定输出该 key（通常为空）"""
        records = list(obj.batch_advance_records.all())
        return PrintingJobBatchAdvanceRecordSerializer(records, many=True).data


class PrintingJobBatchAdvanceRecordSerializer(serializers.ModelSerializer):
    """印染任务批量推进记录（用于嵌入 PrintingJob 的序列化结果）"""

    state_id = serializers.IntegerField(source='state.id', read_only=True)
    state_name = serializers.CharField(source='state.name', read_only=True)
    created_by_username = serializers.CharField(source='created_by.username', read_only=True)
    created_by_name = serializers.SerializerMethodField()

    class Meta:
        model = models.PrintingJobBatchAdvanceRecord
        fields = [
            'id',
            'printing_order',
            'state',
            'state_id',
            'state_name',
            'created_by',
            'created_by_username',
            'created_by_name',
            'parameters',
            'created_at',
        ]
        read_only_fields = fields

    def get_created_by_name(self, obj):
        user = getattr(obj, 'created_by', None)
        if not user:
            return None
        emp = getattr(user, 'employee', None)
        return getattr(emp, 'name', None)


class PlateOrderDesignCodeMixin:
    """确保 design_code 为空时使用主键"""

    @staticmethod
    def _normalize_design_code(design_code: str | None, instance_id: int | None) -> str | None:
        if design_code:
            return design_code
        if instance_id:
            return str(instance_id)
        return design_code

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['design_code'] = self._normalize_design_code(data.get('design_code'), instance.id)
        data['plate_image'] = _serialize_plate_images(getattr(instance, 'plate_image', None), self.context.get('request'))
        return data


class PlateOrderListSerializer(PlateOrderDesignCodeMixin, serializers.ModelSerializer):
    """开版订单列表序列化器"""
    customer_name = serializers.CharField(source="customer.name", read_only=True)
    salesperson_name = serializers.CharField(source="salesperson.name", read_only=True)
    merchandiser_name = serializers.CharField(source="merchandiser.name", read_only=True)
    designer_name = serializers.CharField(source="designer.name", read_only=True)
    status = serializers.CharField(read_only=True)
    progress_percentage = serializers.IntegerField(read_only=True)
    process_name = serializers.SerializerMethodField()
    plate_image_url = serializers.SerializerMethodField()
    last_completed_state = serializers.CharField(read_only=True)
    content_type_id = serializers.SerializerMethodField()
    
    class Meta:
        model = models.PlateOrder

        fields = [
            'id', 'design_code', 'plate_type', 'plate_date', 'plate_method',
            'plate_image', 'plate_image_url', 'image_name', 'plate_notes', 'reprint_reason',
            'urgency_level', 'is_invalid',
            'customer', 'customer_name', 'area', 'default_address',
            'salesperson', 'salesperson_name',
            'merchandiser', 'merchandiser_name',
            'designer', 'designer_name',
            'style_name', 'fabric', 'fabric_source', 'width', 'production_method',
            'is_mark_frame', 'drawing_rating', 'color_matching_rating',
            'sample_rating', 'difficulty_rating',
            'sample_meter', 'required_sample_meters',
            'required_completion_date', 'completion_date',
            'approval_result', 'is_ordered', 'customer_feedback', 'print_count',
            'process', 'process_name',
            'status', 'status_id', 'is_completed', 'has_started', 'last_completed_state',
            'progress_percentage', 'business_object_id', 'content_type_id',
            'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'status', 'progress_percentage', 'last_completed_state',
            'created_at', 'updated_at', 'print_count'
        ]

    def get_plate_image_url(self, obj):
        images = _serialize_plate_images(getattr(obj, 'plate_image', None), self.context.get('request'))
        return [entry.get('url') for entry in images if entry.get('url')]
    
    
    def get_process_name(self, obj) ->str | None:
        """获取流程名称"""
        if obj.process:
            try:
                from stateflow.models import Process
                process = Process.objects.get(id=obj.process)
                return process.name
            except Process.DoesNotExist:
                return None
        return None

    def get_content_type_id(self, obj):
        """
        返回关联流程实例（business_object）的 content_type_id。
        
        - 无 business_object：返回 None
        - business_object 存在但未绑定关联对象：返回 None
        """
        if not getattr(obj, 'business_object_id', None):
            return None
        return obj.business_object.content_type_id


class PlateOrderDetailSerializer(PlateOrderDesignCodeMixin, serializers.ModelSerializer):
    """开版订单详情序列化器"""
    customer_name = serializers.CharField(source="customer.name", read_only=True)
    customer_phone = serializers.CharField(source="customer.mobile", read_only=True)
    salesperson_name = serializers.CharField(source="salesperson.name", read_only=True)
    merchandiser_name = serializers.CharField(source="merchandiser.name", read_only=True)
    designer_name = serializers.CharField(source="designer.name", read_only=True)
    status = serializers.CharField(read_only=True)
    status_id = serializers.IntegerField(read_only=True)
    is_completed = serializers.BooleanField(read_only=True)
    has_started = serializers.BooleanField(read_only=True)
    progress_percentage = serializers.IntegerField(read_only=True)
    business_object_id = serializers.SerializerMethodField()
    plate_image_url = serializers.SerializerMethodField()
    process_name = serializers.SerializerMethodField()
    last_completed_state = serializers.CharField(read_only=True)
    
    class Meta:
        model = models.PlateOrder
        fields = [
            'id', 'design_code', 'plate_type', 'plate_date', 'plate_method',
            'plate_image', 'plate_image_url', 'image_name', 'plate_notes', 'reprint_reason',
            'urgency_level', 'is_invalid',
            'customer', 'customer_name', 'customer_phone', 'area', 'default_address',
            'salesperson', 'salesperson_name',
            'merchandiser', 'merchandiser_name',
            'designer', 'designer_name',
            'style_name', 'fabric', 'fabric_source', 'width', 'production_method',
            'is_mark_frame', 'drawing_rating', 'color_matching_rating',
            'sample_rating', 'difficulty_rating',
            'sample_meter', 'required_sample_meters',
            'required_completion_date', 'completion_date',
            'approval_result', 'is_ordered', 'customer_feedback', 'print_count',
            'process', 'process_name',
            'status', 'status_id', 'is_completed', 'has_started',
            'progress_percentage', 'business_object_id', 'last_completed_state',
            'created_at', 'updated_at'
        ]
        read_only_fields = [
            'id', 'status', 'status_id', 'is_completed', 'has_started',
            'progress_percentage', 'business_object_id', 'last_completed_state',
            'created_at', 'updated_at', 'print_count'
        ]
    
    def get_business_object_id(self, obj):
        """安全地获取 business_object_id"""
        return obj.business_object.id if obj.business_object else None
    
    def get_plate_image_url(self, obj):
        images = _serialize_plate_images(getattr(obj, 'plate_image', None), self.context.get('request'))
        return [entry.get('url') for entry in images if entry.get('url')]
    
    def get_process_name(self, obj):
        """获取流程名称"""
        if obj.process:
            try:
                from stateflow.models import Process
                process = Process.objects.get(id=obj.process)
                return process.name
            except Process.DoesNotExist:
                return None
        return None


class PlateOrderCreateUpdateSerializer(serializers.ModelSerializer):
    """开版订单创建/更新序列化器"""
    plate_image = PlateImageInputSerializer(
        many=True,
        required=False,
        allow_null=True,
        help_text="开版图片列表，需提供已上传的 file_id，可选 name 字段"
    )

    class Meta:
        model = models.PlateOrder
        fields = [
            "id", "design_code", "plate_type", "plate_date", "plate_method",
            "plate_image", "image_name", "plate_notes", "reprint_reason",
            "urgency_level", "is_invalid",
            "customer", "area", "default_address",
            "salesperson", "merchandiser", "designer",
            "style_name", "fabric", "fabric_source", "width", "production_method",
            "is_mark_frame", "drawing_rating", "color_matching_rating",
            "sample_rating", "difficulty_rating",
            "sample_meter", "required_sample_meters",
            "required_completion_date", "completion_date",
            "approval_result", "is_ordered", "customer_feedback",
            "process"
        ]
        read_only_fields = ["id"]

    def validate_plate_image(self, value):
        return value or []

    def validate_customer(self, value):
        """验证客户是否存在"""
        if not value:
            raise serializers.ValidationError("客户不能为空")
        return value
    
    def validate_salesperson(self, value):
        """验证业务员是否存在"""
        if value and not Employee.objects.filter(id=value.id).exists():
            raise serializers.ValidationError("业务员不存在")
        return value
    
    def validate_merchandiser(self, value):
        """验证跟单员是否存在"""
        if value and not Employee.objects.filter(id=value.id).exists():
            raise serializers.ValidationError("跟单员不存在")
        return value
    
    def validate_designer(self, value):
        """验证设计师是否存在"""
        if value and not Employee.objects.filter(id=value.id).exists():
            raise serializers.ValidationError("设计师不存在")
        return value
    
    def validate_sample_meter(self, value):
        """验证样品米数"""
        if value is not None and value < 0:
            raise serializers.ValidationError("样品米数不能为负数")
        return value
    
    def validate_required_sample_meters(self, value):
        """验证所需样品米数"""
        if value is not None and value < 0:
            raise serializers.ValidationError("所需样品米数不能为负数")
        return value
    
    def validate_process(self, value):
        """验证流程是否存在"""
        if value:
            from stateflow.models import Process
            if not Process.objects.filter(id=value).exists():
                raise serializers.ValidationError("流程不存在")
        return value
    
    def validate(self, attrs):
        """交叉验证"""
        return attrs
    
    def create(self, validated_data):
        plate_images = validated_data.pop('plate_image', None)
        if plate_images is not None:
            validated_data['plate_image'] = _build_plate_image_payload(plate_images, self._request_user)
        return super().create(validated_data)
    
    def update(self, instance, validated_data):
        plate_images = validated_data.pop('plate_image', None)
        if plate_images is not None:
            validated_data['plate_image'] = _build_plate_image_payload(plate_images, self._request_user)
        return super().update(instance, validated_data)

    @property
    def _request_user(self):
        request = self.context.get('request')
        return getattr(request, 'user', None)
