"""
Shipment API 序列化器
"""

from rest_framework import serializers

from shipment.models import (
    ExternalFinishedProduct,
    SalesItem,
    Shipment,
    ShipmentStatus,
    ShipmentDelivery,
    ShipmentDeliveryStatus,
)


def _build_nested_sales_item_context(items):
    customer_ids = {item.customer_id for item in items if item.customer_id}
    printing_job_ids = {item.printing_job_id for item in items if item.printing_job_id}

    customer_name_map = {}
    if customer_ids:
        from basic_info.models import Customer

        customer_name_map = dict(
            Customer.objects.filter(id__in=customer_ids).values_list("id", "name")
        )

    printing_order_map = {}
    external_order_id_map = {}
    product_image_map = {}
    if printing_job_ids:
        from printing.models import PrintingJob

        printing_jobs = list(
            PrintingJob.objects.filter(id__in=printing_job_ids).select_related(
                "printing_order", "product"
            )
        )
        printing_order_map = {job.id: job.printing_order_id for job in printing_jobs}
        external_order_id_map = {
            job.id: getattr(job.printing_order, "external_order_id", None)
            for job in printing_jobs
        }
        for job in printing_jobs:
            if not getattr(job, "product", None):
                product_image_map[job.id] = None
                continue
            primary_url = job.product.get_primary_image_url()
            if primary_url:
                product_image_map[job.id] = primary_url
            elif job.product.image:
                product_image_map[job.id] = job.product.image.url
            else:
                product_image_map[job.id] = None

    return {
        "customer_name_map": customer_name_map,
        "printing_order_map": printing_order_map,
        "external_order_id_map": external_order_id_map,
        "product_image_map": product_image_map,
    }


def _resolve_shipment_fabric(shipment: Shipment) -> str | None:
    rel = getattr(shipment, "items", None)
    if rel is None:
        return None

    first_item = rel.filter(delete_at__isnull=True).order_by("id").first()
    if first_item is None or not first_item.printing_job_id:
        return None

    from printing.models import PrintingJob

    printing_job = (
        PrintingJob.objects.filter(id=first_item.printing_job_id)
        .select_related("printing_order")
        .first()
    )
    if printing_job is None or printing_job.printing_order is None:
        return None
    return printing_job.printing_order.fabric


def _resolve_shipment_order_description(shipment: Shipment) -> str | None:
    rel = getattr(shipment, "items", None)
    if rel is None:
        return None

    first_item = rel.filter(delete_at__isnull=True).order_by("id").first()
    if first_item is None or not first_item.printing_job_id:
        return None

    from printing.models import PrintingJob

    printing_job = (
        PrintingJob.objects.filter(id=first_item.printing_job_id)
        .select_related("printing_order")
        .first()
    )
    if printing_job is None or printing_job.printing_order is None:
        return None
    # 目前滚筒预警字段被放在了 printing_order 上，暂时沿用这个字段来返回订单描述；
    return printing_job.printing_order.rolling_warn


class ShipmentSerializer(serializers.ModelSerializer):
    """
    出货单序列化器（只读，用于返回数据）
    """

    customer_name = serializers.CharField(source="customer.name", read_only=True)
    created_by_id = serializers.IntegerField(
        source="created_by.id", read_only=True, allow_null=True
    )
    created_by_name = serializers.SerializerMethodField()
    items_count = serializers.SerializerMethodField()
    cancelled_by_id = serializers.IntegerField(
        source="cancelled_by.id", read_only=True, allow_null=True
    )
    cancelled_by_name = serializers.SerializerMethodField()
    approved_by_id = serializers.IntegerField(
        source="approved_by.id", read_only=True, allow_null=True
    )
    approved_by_name = serializers.SerializerMethodField()
    status_display = serializers.CharField(source="get_status_display", read_only=True)
    external_finished_products_count = serializers.SerializerMethodField()
    merchant_id = serializers.IntegerField(source="merchant.id", read_only=True)
    merchant_name = serializers.CharField(source="merchant.name", read_only=True)
    fabric = serializers.SerializerMethodField()
    order_description = serializers.SerializerMethodField()
    delivery_id = serializers.IntegerField(read_only=True, allow_null=True)
    sales_items = serializers.SerializerMethodField()
    external_finished_products = serializers.SerializerMethodField()

    class Meta:
        model = Shipment
        fields = [
            "id",
            "merchant_id",
            "merchant_name",
            "customer",
            "customer_name",
            "fabric",
            "order_description",
            "shipment_date",
            "address",
            "contact_name",
            "contact_phone",
            "area",
            "remark",
            "status",
            "status_display",
            "external_id",
            "geo_coordinates",
            "delivery_id",
            "status_modified_at",
            "cancelled_by_id",
            "cancelled_by_name",
            "approved_by_id",
            "approved_by_name",
            "items_count",
            "created_by_id",
            "created_by_name",
            "external_finished_products_count",
            "sales_items",
            "external_finished_products",
            "created_at",
            "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]

    def get_created_by_name(self, obj):
        if obj.created_by:
            employee = getattr(obj.created_by, "employee", None)
            if employee:
                return employee.name
            return obj.created_by.username
        return None

    def get_fabric(self, obj):
        return _resolve_shipment_fabric(obj)

    def get_items_count(self, obj):
        return obj.items.filter(delete_at__isnull=True).count()

    def get_order_description(self, obj):
        return _resolve_shipment_order_description(obj)

    def get_cancelled_by_name(self, obj):
        if obj.cancelled_by:
            employee = getattr(obj.cancelled_by, "employee", None)
            if employee:
                return employee.name
            return obj.cancelled_by.username
        return None

    def get_external_finished_products_count(self, obj):
        return obj.external_finished_products.count()

    def get_approved_by_name(self, obj):
        if obj.approved_by:
            employee = getattr(obj.approved_by, "employee", None)
            if employee:
                return employee.name
            return obj.approved_by.username
        return None

    def get_sales_items(self, obj):
        """
        出货单关联的销售品明细（无则返回空数组）。
        """
        # 优先使用 prefetch 的 related manager；兜底为 none()
        rel = getattr(obj, "items", None)
        items = list(rel.filter(delete_at__isnull=True)) if rel is not None else []
        serializer_context = dict(self.context)
        serializer_context.update(_build_nested_sales_item_context(items))
        return SalesItemDetailSerializer(
            items,
            many=True,
            context=serializer_context,
        ).data

    def get_external_finished_products(self, obj):
        """
        出货单关联的外部成品表明细（无则返回空数组）。
        """
        rel = getattr(obj, "external_finished_products", None)
        products = list(rel.all()) if rel is not None else []
        return ExternalFinishedProductSerializer(products, many=True).data


class ExternalFinishedProductSerializer(serializers.ModelSerializer):
    """
    外部成品表序列化器（只读）
    """

    created_by_id = serializers.IntegerField(
        source="created_by.id", read_only=True, allow_null=True
    )
    created_by_name = serializers.SerializerMethodField()

    class Meta:
        model = ExternalFinishedProduct
        fields = [
            "id",
            "style_name",
            "num_of_rolls",
            "remark",
            "created_at",
            "created_by_id",
            "created_by_name",
        ]
        read_only_fields = fields

    def get_created_by_name(self, obj):
        if obj.created_by:
            employee = getattr(obj.created_by, "employee", None)
            if employee:
                return employee.name
            return obj.created_by.username
        return None


class ShipmentCreateNormalSerializer(serializers.Serializer):
    """
    出货单创建序列化器（普通版）
    """

    customer = serializers.IntegerField(help_text="客户ID")
    shipment_date = serializers.DateField(help_text="出货日期")
    address = serializers.CharField(
        max_length=255,
        required=False,
        default="",
        allow_blank=True,
        help_text="地址（可选）",
    )
    contact_name = serializers.CharField(
        max_length=100,
        required=False,
        default="",
        allow_blank=True,
        help_text="联系人（可选）",
    )
    contact_phone = serializers.CharField(
        max_length=50,
        required=False,
        default="",
        allow_blank=True,
        help_text="联系电话（可选）",
    )
    area = serializers.CharField(
        max_length=30,
        required=False,
        default="",
        allow_blank=True,
        help_text="出货地区（可选）",
    )
    remark = serializers.CharField(
        required=False, default="", allow_blank=True, help_text="备注"
    )
    sales_items = serializers.ListField(
        child=serializers.IntegerField(),
        required=False,
        default=list,
        help_text="要关联的销售品ID列表",
    )

    def validate_sales_items(self, value):
        # 去重
        return list(set(value)) if value else []


class ExternalFinishedProductInputSerializer(serializers.Serializer):
    """外部成品表写入结构（external create 专用）"""

    style_name = serializers.CharField(max_length=200)
    num_of_rolls = serializers.IntegerField(min_value=0)
    remark = serializers.CharField(
        max_length=200, required=False, allow_blank=True, allow_null=True, default=""
    )


class ShipmentCreateExternalSerializer(serializers.Serializer):
    """
    出货单创建序列化器（external 版）

    特点：
    - 不绑定任何 SalesItem
    - 必须提供 external_id
    - 同时写入 ExternalFinishedProduct 列表并关联到 Shipment
    """

    customer = serializers.IntegerField(help_text="客户ID")
    shipment_date = serializers.DateField(help_text="出货日期")
    address = serializers.CharField(
        max_length=255,
        required=False,
        default="",
        allow_blank=True,
        help_text="地址（可选）",
    )
    contact_name = serializers.CharField(
        max_length=100,
        required=False,
        default="",
        allow_blank=True,
        help_text="联系人（可选）",
    )
    contact_phone = serializers.CharField(
        max_length=50,
        required=False,
        default="",
        allow_blank=True,
        help_text="联系电话（可选）",
    )
    area = serializers.CharField(
        max_length=30,
        required=False,
        default="",
        allow_blank=True,
        help_text="出货地区（可选）",
    )
    remark = serializers.CharField(
        required=False, default="", allow_blank=True, help_text="备注"
    )
    external_id = serializers.CharField(max_length=120, help_text="外部订单号（必填）")
    external_finished_products = serializers.ListField(
        child=ExternalFinishedProductInputSerializer(),
        required=True,
        help_text="外部成品表结构数组（必填）",
    )

    def validate_external_id(self, value):
        value = (value or "").strip()
        if not value:
            raise serializers.ValidationError("external_id 不能为空")
        return value

    def validate_external_finished_products(self, value):
        if not value:
            raise serializers.ValidationError("external_finished_products 不能为空")
        return value


class ShipmentUpdateSerializer(serializers.Serializer):
    """
    出货单更新序列化器（PATCH/PUT）

    说明：本次新增字段 area，需要保证更新入口可写入并回显。
    """

    customer = serializers.IntegerField(required=False, help_text="客户ID（可选）")
    shipment_date = serializers.DateField(required=False, help_text="出货日期（可选）")
    address = serializers.CharField(
        max_length=255, required=False, allow_blank=True, help_text="地址（可选）"
    )
    contact_name = serializers.CharField(
        max_length=100, required=False, allow_blank=True, help_text="联系人（可选）"
    )
    contact_phone = serializers.CharField(
        max_length=50, required=False, allow_blank=True, help_text="联系电话（可选）"
    )
    area = serializers.CharField(
        max_length=30, required=False, allow_blank=True, help_text="出货地区（可选）"
    )
    remark = serializers.CharField(
        required=False, allow_blank=True, help_text="备注（可选）"
    )
    external_id = serializers.CharField(
        max_length=120,
        required=False,
        allow_blank=True,
        allow_null=True,
        help_text="外部订单号（可选）",
    )
    geo_coordinates = serializers.JSONField(
        required=False,
        allow_null=True,
        help_text="Geo 系统返回的坐标信息（可空，结构不作校验）",
    )


class ShipmentStatusUpdateSerializer(serializers.Serializer):
    status = serializers.ChoiceField(
        choices=ShipmentStatus.choices,
        help_text="出货单状态（1=草稿(未发布), 2=已发布, 3=已取消, 4=已驳回, 5=已审核）",
    )


class SalesItemSerializer(serializers.Serializer):
    """
    销售品序列化器（只读）

    用于返回销售品数据
    """

    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(read_only=True)
    quantity = serializers.DecimalField(max_digits=12, decimal_places=2, read_only=True)
    unit = serializers.IntegerField(read_only=True)
    unit_display = serializers.SerializerMethodField()
    position = serializers.CharField(read_only=True)
    remark = serializers.CharField(read_only=True)
    printing_job_id = serializers.IntegerField(read_only=True)
    printing_order_id = serializers.SerializerMethodField()
    external_order_id = serializers.SerializerMethodField()
    customer_id = serializers.IntegerField(read_only=True)
    customer_name = serializers.SerializerMethodField()
    shipment_id = serializers.IntegerField(
        source="shipment.id", read_only=True, allow_null=True
    )
    shipment_date = serializers.DateField(
        source="shipment.shipment_date", read_only=True, allow_null=True
    )
    merge_remark = serializers.JSONField(read_only=True, allow_null=True)
    created_at = serializers.DateTimeField(read_only=True)
    created_by_id = serializers.IntegerField(
        source="created_by.id", read_only=True, allow_null=True
    )
    created_by_name = serializers.SerializerMethodField()

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

    def get_printing_order_id(self, obj):
        printing_order_map = self.context.get("printing_order_map", {})
        if obj.printing_job_id in printing_order_map:
            return printing_order_map[obj.printing_job_id]

        printing_job = obj.get_printing_job()
        if printing_job and getattr(printing_job, "printing_order_id", None):
            return printing_job.printing_order_id
        return None

    def get_external_order_id(self, obj):
        external_order_id_map = self.context.get("external_order_id_map", {})
        if obj.printing_job_id in external_order_id_map:
            return external_order_id_map[obj.printing_job_id]

        printing_job = obj.get_printing_job()
        if printing_job and getattr(printing_job.printing_order, "external_order_id", None):
            return printing_job.printing_order.external_order_id
        return None

    def get_customer_name(self, obj):
        customer_name_map = self.context.get("customer_name_map", {})
        if obj.customer_id in customer_name_map:
            return customer_name_map[obj.customer_id]

        customer = obj.get_customer()
        return customer.name if customer else None

    def get_created_by_name(self, obj):
        if obj.created_by:
            employee = getattr(obj.created_by, "employee", None)
            if employee:
                return employee.name
            return obj.created_by.username
        return None


class SalesItemDetailSerializer(SalesItemSerializer):
    """
    销售品详情序列化器。

    在列表字段基础上补充关联印染任务的产品图片。
    """

    product_image_url = serializers.SerializerMethodField()

    def get_product_image_url(self, obj):
        product_image_map = self.context.get("product_image_map", {})
        if obj.printing_job_id in product_image_map:
            return product_image_map[obj.printing_job_id]

        printing_job = obj.get_printing_job()
        if not printing_job or not getattr(printing_job, "product", None):
            return None

        primary_url = printing_job.product.get_primary_image_url()
        if primary_url:
            return primary_url

        if printing_job.product.image:
            request = self.context.get("request")
            if request:
                return request.build_absolute_uri(printing_job.product.image.url)
            return printing_job.product.image.url
        return None


class ShipmentSalesItemCustomerSerializer(serializers.Serializer):
    """
    由未出货销售品反推的客户摘要序列化器。
    """

    customer_id = serializers.IntegerField(source="id", read_only=True)
    customer_name = serializers.CharField(source="name", read_only=True)
    mobile = serializers.CharField(read_only=True, allow_null=True)
    area = serializers.CharField(read_only=True, allow_null=True)
    unshipped_sales_items_count = serializers.IntegerField(read_only=True)


class ShipmentDeliveryShipmentSummarySerializer(serializers.ModelSerializer):
    customer_name = serializers.CharField(source="customer.name", read_only=True)
    status_display = serializers.CharField(source="get_status_display", read_only=True)
    fabric = serializers.SerializerMethodField()
    order_description = serializers.SerializerMethodField()
    delivery_id = serializers.IntegerField(read_only=True, allow_null=True)

    class Meta:
        model = Shipment
        fields = [
            "id",
            "customer",
            "customer_name",
            "fabric",
            "order_description",
            "shipment_date",
            "status",
            "status_display",
            "external_id",
            "delivery_id",
        ]
        read_only_fields = fields

    def get_fabric(self, obj):
        return _resolve_shipment_fabric(obj)

    def get_order_description(self, obj):
        return _resolve_shipment_order_description(obj)


class ShipmentDeliverySerializer(serializers.ModelSerializer):
    status_display = serializers.CharField(source="get_status_display", read_only=True)
    merchant_id = serializers.IntegerField(source="merchant.id", read_only=True)
    merchant_name = serializers.CharField(source="merchant.name", read_only=True)
    created_by_id = serializers.IntegerField(
        source="created_by.id", read_only=True, allow_null=True
    )
    created_by_name = serializers.SerializerMethodField()
    operator_id = serializers.IntegerField(
        source="operator.id", read_only=True, allow_null=True
    )
    operator_name = serializers.CharField(source="operator.name", read_only=True, allow_null=True)
    cancelled_by_id = serializers.IntegerField(
        source="cancelled_by.id", read_only=True, allow_null=True
    )
    cancelled_by_name = serializers.SerializerMethodField()
    shipments_count = serializers.SerializerMethodField()
    shipments = serializers.SerializerMethodField()

    class Meta:
        model = ShipmentDelivery
        fields = [
            "id",
            "merchant_id",
            "merchant_name",
            "driver_name",
            "vehicle_trip",
            "contact_phone",
            "vehicle_capacity",
            "remark",
            "internal_remark",
            "shipment_order_ids",
            "status",
            "status_display",
            "started_at",
            "delivered_at",
            "cancelled_at",
            "shipments_count",
            "shipments",
            "created_by_id",
            "created_by_name",
            "operator_id",
            "operator_name",
            "cancelled_by_id",
            "cancelled_by_name",
            "created_at",
            "updated_at",
        ]
        read_only_fields = fields

    def get_created_by_name(self, obj):
        if obj.created_by:
            employee = getattr(obj.created_by, "employee", None)
            if employee:
                return employee.name
            return obj.created_by.username
        return None

    def get_cancelled_by_name(self, obj):
        if obj.cancelled_by:
            employee = getattr(obj.cancelled_by, "employee", None)
            if employee:
                return employee.name
            return obj.cancelled_by.username
        return None

    def get_shipments_count(self, obj):
        return obj.shipments.count()

    def get_shipments(self, obj):
        return ShipmentDeliveryShipmentSummarySerializer(
            obj.shipments.order_by("id"),
            many=True,
        ).data


class ShipmentDeliveryCreateSerializer(serializers.Serializer):
    driver_name = serializers.CharField(max_length=100, help_text="司机名")
    vehicle_trip = serializers.CharField(max_length=100, help_text="车次")
    contact_phone = serializers.CharField(
        max_length=50,
        required=False,
        default="",
        allow_blank=True,
        help_text="联系电话（可选）",
    )
    vehicle_capacity = serializers.CharField(
        max_length=100,
        required=False,
        default="",
        allow_blank=True,
        help_text="车辆容量（可选）",
    )
    remark = serializers.CharField(
        max_length=200,
        required=False,
        default="",
        allow_blank=True,
        help_text="备注（可选）",
    )
    internal_remark = serializers.CharField(
        max_length=200,
        required=False,
        default="",
        allow_blank=True,
        help_text="内部备注（可选）",
    )
    shipment_order_ids = serializers.JSONField(
        required=False,
        allow_null=True,
        default=list,
        help_text="前端自管的出货单顺序 ID 数组（可选，可为 null）",
    )
    shipments = serializers.ListField(
        child=serializers.IntegerField(),
        required=False,
        default=list,
        help_text="要关联的出货单ID列表",
    )

    def validate_shipments(self, value):
        return list(dict.fromkeys(value)) if value else []

    def validate_shipment_order_ids(self, value):
        if value is not None and not isinstance(value, list):
            raise serializers.ValidationError("shipment_order_ids 必须是数组或 null")
        return value


class ShipmentDeliveryUpdateSerializer(serializers.Serializer):
    driver_name = serializers.CharField(
        max_length=100, required=False, allow_blank=False, help_text="司机名（可选）"
    )
    vehicle_trip = serializers.CharField(
        max_length=100, required=False, allow_blank=False, help_text="车次（可选）"
    )
    contact_phone = serializers.CharField(
        max_length=50, required=False, allow_blank=True, help_text="联系电话（可选）"
    )
    vehicle_capacity = serializers.CharField(
        max_length=100, required=False, allow_blank=True, help_text="车辆容量（可选）"
    )
    remark = serializers.CharField(
        max_length=200, required=False, allow_blank=True, help_text="备注（可选）"
    )
    internal_remark = serializers.CharField(
        max_length=200, required=False, allow_blank=True, help_text="内部备注（可选）"
    )
    shipment_order_ids = serializers.JSONField(
        required=False,
        allow_null=True,
        help_text="前端自管的出货单顺序 ID 数组（可选，可为 null）",
    )
    shipments = serializers.ListField(
        child=serializers.IntegerField(),
        required=False,
        help_text="要绑定的出货单ID列表（可选，传入即视为替换）",
    )

    def validate_shipments(self, value):
        return list(dict.fromkeys(value)) if value else []

    def validate_shipment_order_ids(self, value):
        if value is not None and not isinstance(value, list):
            raise serializers.ValidationError("shipment_order_ids 必须是数组或 null")
        return value


class ShipmentDeliveryStatusUpdateSerializer(serializers.Serializer):
    status = serializers.ChoiceField(
        choices=[
            (ShipmentDeliveryStatus.PENDING, ShipmentDeliveryStatus.PENDING.label),
            (ShipmentDeliveryStatus.IN_TRANSIT, ShipmentDeliveryStatus.IN_TRANSIT.label),
            (ShipmentDeliveryStatus.DELIVERED, ShipmentDeliveryStatus.DELIVERED.label),
        ],
        help_text="送货单状态（1=待送货, 2=送货中, 3=已送达）",
    )


class ShipmentDeliveryBindShipmentsSerializer(serializers.Serializer):
    shipments = serializers.ListField(
        child=serializers.IntegerField(),
        required=True,
        help_text="要追加绑定到当前送货单的出货单ID列表",
    )

    def validate_shipments(self, value):
        if not value:
            raise serializers.ValidationError("shipments 不能为空")
        return list(dict.fromkeys(value))


class SalesItemCreateSerializer(serializers.Serializer):
    """
    销售品创建序列化器

    用于手动创建销售品（当自动转化开关关闭时使用）
    """

    printing_job_id = serializers.IntegerField(
        required=True, min_value=1, help_text="生产任务ID（必填）"
    )
    name = serializers.CharField(
        max_length=200, required=True, help_text="销售品名称（必填）"
    )
    quantity = serializers.CharField(
        max_length=20, required=True, help_text="数量（必填，支持小数，如：100.50）"
    )
    unit = serializers.IntegerField(
        required=True, help_text="单位（必填）：1=米, 2=件, 3=码, 4=个"
    )
    customer_id = serializers.IntegerField(
        required=False, allow_null=True, help_text="客户ID（可选，默认从生产订单获取）"
    )
    remark = serializers.CharField(
        max_length=200,
        required=False,
        allow_blank=True,
        default="",
        help_text="备注（可选）",
    )
    position = serializers.CharField(
        max_length=200,
        required=False,
        allow_blank=True,
        default="",
        help_text="货位（可选）",
    )
    merge_remark = serializers.JSONField(
        required=False,
        allow_null=True,
        default=None,
        help_text="合卷备注JSON（可选）",
    )

    _MERGE_REMARK_REQUIRED_KEYS = {
        "merge_type": str,
        "jobs": list,
        "main_job": int,
        "quantity": str,
        "unit": str,
        "job_count": int,
    }

    def validate_merge_remark(self, value):
        """严格校验 merge_remark 的结构"""
        if value is None:
            return value
        if not isinstance(value, dict):
            raise serializers.ValidationError("merge_remark 必须是一个 JSON 对象")

        missing = set(self._MERGE_REMARK_REQUIRED_KEYS) - set(value.keys())
        if missing:
            raise serializers.ValidationError(f"缺少必填字段: {sorted(missing)}")

        extra = set(value.keys()) - set(self._MERGE_REMARK_REQUIRED_KEYS)
        if extra:
            raise serializers.ValidationError(f"包含未知字段: {sorted(extra)}")

        for key, expected_type in self._MERGE_REMARK_REQUIRED_KEYS.items():
            if not isinstance(value[key], expected_type):
                raise serializers.ValidationError(
                    f"字段 '{key}' 类型错误，期望 {expected_type.__name__}，"
                    f"实际 {type(value[key]).__name__}"
                )

        # jobs 列表内的元素必须都是整数
        if not all(isinstance(j, int) for j in value["jobs"]):
            raise serializers.ValidationError("jobs 列表中的元素必须为整数")

        if len(value["jobs"]) < 2:
            raise serializers.ValidationError("jobs 列表至少需要包含 2 个子单ID")

        if value["main_job"] not in value["jobs"]:
            raise serializers.ValidationError("main_job 必须是 jobs 列表中的一个成员")

        if value["job_count"] != len(value["jobs"]):
            raise serializers.ValidationError(
                f"job_count ({value['job_count']}) 与 jobs 长度 ({len(value['jobs'])}) 不一致"
            )

        return value

    def validate_unit(self, value):
        """验证单位值是否在允许范围内"""
        from shipment.models import UnitChoices

        valid_units = [choice[0] for choice in UnitChoices.choices]
        if value not in valid_units:
            raise serializers.ValidationError(
                f"单位值无效。可选值：{dict(UnitChoices.choices)}"
            )
        return value

    def create(self, validated_data):
        """创建销售品"""
        from shipment.services import create_sales_item

        # 获取当前用户（从context传入）
        created_by = self.context["request"].user

        return create_sales_item(
            printing_job_id=validated_data["printing_job_id"],
            name=validated_data["name"],
            quantity=validated_data["quantity"],
            unit=validated_data["unit"],
            created_by=created_by,
            customer_id=validated_data.get("customer_id"),
            remark=validated_data.get("remark", ""),
            position=validated_data.get("position", ""),
            merge_remark=validated_data.get("merge_remark"),
        )


class SalesItemUpdateSerializer(serializers.Serializer):
    """
    销售品更新序列化器。

    当前仅开放数量、备注、货位的修改。
    """

    quantity = serializers.CharField(
        max_length=20,
        required=False,
        help_text="数量（可选，支持小数）",
    )
    remark = serializers.CharField(
        max_length=200,
        required=False,
        allow_blank=True,
        help_text="备注（可选）",
    )
    position = serializers.CharField(
        max_length=200,
        required=False,
        allow_blank=True,
        help_text="货位（可选）",
    )

    def validate(self, attrs):
        if not attrs:
            raise serializers.ValidationError("至少提供一个可修改字段")
        return attrs


class SalesItemRebuildSerializer(serializers.Serializer):
    """
    销售品重建序列化器。
    """

    new_printing_job_id = serializers.IntegerField(
        required=True,
        min_value=1,
        help_text="新的生产任务ID（必填）",
    )
    quantity = serializers.CharField(
        max_length=20,
        required=False,
        allow_blank=False,
        help_text="新的数量（可选，未传则沿用原销售品数量）",
    )
