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

from rest_framework import serializers

from shipment.models import ExternalFinishedProduct, SalesItem, Shipment


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()
    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)
    sales_items = serializers.SerializerMethodField()
    external_finished_products = serializers.SerializerMethodField()

    class Meta:
        model = Shipment
        fields = [
            "id",
            "merchant_id",
            "merchant_name",
            "customer",
            "customer_name",
            "shipment_date",
            "area",
            "remark",
            "status",
            "status_display",
            "external_id",
            "cancelled_at",
            "cancelled_by_id",
            "cancelled_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_items_count(self, obj):
        return obj.items.count()

    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_sales_items(self, obj):
        """
        出货单关联的销售品明细（无则返回空数组）。
        """
        # 优先使用 prefetch 的 related manager；兜底为 none()
        rel = getattr(obj, "items", None)
        items = list(rel.all()) if rel is not None else []
        return SalesItemSerializer(items, many=True).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="出货日期")
    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="出货日期")
    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="出货日期（可选）")
    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="外部订单号（可选）",
    )


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)
    customer_id = serializers.IntegerField(read_only=True)
    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
    )
    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_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 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="货位（可选）",
    )

    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", ""),
        )
