"""
SCM API Serializers — v1.

سریالایزرهای REST API ماژول خرید و تدارکات.
"""
from rest_framework import serializers

from ...infrastructure.persistence.models import (
    VendorCategoryModel,
    VendorModel,
    VendorContactModel,
    VendorBankAccountModel,
    VendorAddressModel,
)
from ...infrastructure.persistence.models_extended import (
    PurchaseRequisitionModel,
    PurchaseRequisitionLineModel,
    RFQModel,
    RFQLineModel,
    RFQVendorResponseModel,
    RFQVendorResponseLineModel,
    PurchaseOrderModel,
    PurchaseOrderLineModel,
    GoodsReceiptModel,
    GoodsReceiptLineModel,
    PurchaseReturnModel,
    PurchaseReturnLineModel,
    VendorEvaluationModel,
    VendorEvaluationScoreModel,
    EvaluationCriteriaModel,
    EvaluationPeriodModel,
    VendorPriceListModel,
    VendorPriceListItemModel,
    PurchaseDiscountModel,
)


# ═══════════════════════════════════════════════════
# 1. Vendor Management
# ═══════════════════════════════════════════════════

class VendorCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorCategoryModel
        fields = [
            "id", "category_code", "category_name",
            "parent_category", "level", "description",
            "is_active", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class VendorCategoryListSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorCategoryModel
        fields = ["id", "category_code", "category_name", "level", "is_active"]


class VendorSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorModel
        fields = [
            "id", "vendor_code", "vendor_name", "vendor_name_en",
            "vendor_type", "category", "status",
            "national_id", "economic_code", "registration_number",
            "phone", "fax", "email", "website",
            "representative_employee_id",
            "payment_terms_days", "credit_limit", "currency_code",
            "notes", "is_active",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class VendorListSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source="category.category_name", read_only=True, default="")

    class Meta:
        model = VendorModel
        fields = [
            "id", "vendor_code", "vendor_name", "vendor_type",
            "status", "category_name", "phone", "is_active",
        ]


class VendorCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorModel
        fields = [
            "vendor_code", "vendor_name", "vendor_name_en",
            "vendor_type", "category",
            "national_id", "economic_code", "registration_number",
            "phone", "fax", "email", "website",
            "representative_employee_id",
            "payment_terms_days", "credit_limit", "currency_code",
            "notes",
        ]


class VendorContactSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorContactModel
        fields = [
            "id", "vendor", "contact_name", "contact_title",
            "phone", "mobile", "email",
            "is_primary", "is_active",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class VendorBankAccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorBankAccountModel
        fields = [
            "id", "vendor", "bank_name", "branch_name",
            "account_number", "iban", "account_holder_name",
            "is_default", "is_active",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class VendorAddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorAddressModel
        fields = [
            "id", "vendor", "address_type",
            "address_line1", "address_line2",
            "city", "province", "postal_code", "country",
            "phone", "fax", "is_default",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class VendorBlockSerializer(serializers.Serializer):
    reason = serializers.CharField(required=False, allow_blank=True)


# ═══════════════════════════════════════════════════
# 2. Purchase Requisition
# ═══════════════════════════════════════════════════

class PRLineSerializer(serializers.ModelSerializer):
    class Meta:
        model = PurchaseRequisitionLineModel
        fields = [
            "id", "requisition", "line_number",
            "item_id", "item_code", "item_name", "description",
            "quantity", "uom_id", "uom_code",
            "estimated_unit_price", "estimated_total_price",
            "required_date", "warehouse_id", "warehouse_name",
            "preferred_vendor_id", "notes",
            "is_converted", "converted_po_id",
        ]
        read_only_fields = ["id", "requisition", "estimated_total_price"]


class PRSerializer(serializers.ModelSerializer):
    lines = PRLineSerializer(many=True, read_only=True)

    class Meta:
        model = PurchaseRequisitionModel
        fields = [
            "id", "pr_number", "title", "description",
            "status", "priority",
            "requester_id", "requester_name", "department",
            "request_date", "required_date",
            "total_estimated_amount", "currency_code",
            "approved_by_id", "approved_at", "rejection_reason",
            "notes", "lines",
            "created_at", "updated_at",
        ]
        read_only_fields = [
            "id", "status", "total_estimated_amount",
            "approved_by_id", "approved_at", "rejection_reason",
            "created_at", "updated_at",
        ]


class PRListSerializer(serializers.ModelSerializer):
    class Meta:
        model = PurchaseRequisitionModel
        fields = [
            "id", "pr_number", "title", "status", "priority",
            "requester_name", "department",
            "total_estimated_amount", "required_date",
            "created_at",
        ]


class PRCreateSerializer(serializers.ModelSerializer):
    lines = PRLineSerializer(many=True)

    class Meta:
        model = PurchaseRequisitionModel
        fields = [
            "pr_number", "title", "description", "priority",
            "requester_id", "requester_name", "department",
            "required_date", "currency_code", "notes",
            "lines",
        ]

    def create(self, validated_data):
        lines_data = validated_data.pop("lines", [])
        pr = PurchaseRequisitionModel.objects.create(**validated_data)
        for idx, line_data in enumerate(lines_data, start=1):
            line_data["line_number"] = idx
            line_data["requisition"] = pr
            if "tenant" not in line_data and hasattr(pr, "tenant"):
                line_data["tenant"] = pr.tenant
            PurchaseRequisitionLineModel.objects.create(**line_data)
        # Recalculate totals
        total = sum(
            (ln.quantity or 0) * (ln.estimated_unit_price or 0)
            for ln in pr.lines.all()
        )
        pr.total_estimated_amount = total
        pr.save(update_fields=["total_estimated_amount"])
        return pr


class PRRejectSerializer(serializers.Serializer):
    reason = serializers.CharField(required=False, allow_blank=True)


# ═══════════════════════════════════════════════════
# 3. RFQ
# ═══════════════════════════════════════════════════

class RFQLineSerializer(serializers.ModelSerializer):
    class Meta:
        model = RFQLineModel
        fields = [
            "id", "rfq", "line_number",
            "item_id", "item_code", "item_name", "description",
            "quantity", "uom_id", "uom_code",
            "required_date", "notes",
        ]
        read_only_fields = ["id"]


class RFQVendorResponseLineSerializer(serializers.ModelSerializer):
    class Meta:
        model = RFQVendorResponseLineModel
        fields = [
            "id", "response", "rfq_line", "line_number",
            "unit_price", "total_price", "delivery_days", "notes",
        ]
        read_only_fields = ["id"]


class RFQVendorResponseSerializer(serializers.ModelSerializer):
    lines = RFQVendorResponseLineSerializer(many=True, read_only=True)
    vendor_id = serializers.UUIDField()
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = RFQVendorResponseModel
        fields = [
            "id", "rfq", "vendor_id", "vendor_name",
            "status", "response_date", "validity_date",
            "total_amount", "currency_code",
            "payment_terms", "delivery_terms", "notes",
            "lines",
        ]
        read_only_fields = ["id"]


class RFQSerializer(serializers.ModelSerializer):
    lines = RFQLineSerializer(many=True, read_only=True)
    vendor_responses = RFQVendorResponseSerializer(many=True, read_only=True)

    class Meta:
        model = RFQModel
        fields = [
            "id", "rfq_number", "title", "description",
            "status", "pr_id", "pr_number",
            "issue_date", "closing_date", "required_date",
            "buyer_id", "buyer_name",
            "currency_code", "notes",
            "lines", "vendor_responses",
            "created_at", "updated_at",
        ]
        read_only_fields = [
            "id", "status", "issue_date",
            "created_at", "updated_at",
        ]


class RFQListSerializer(serializers.ModelSerializer):
    class Meta:
        model = RFQModel
        fields = [
            "id", "rfq_number", "title", "status",
            "closing_date", "buyer_name",
            "created_at",
        ]


class RFQAwardSerializer(serializers.Serializer):
    vendor_id = serializers.UUIDField()


# ═══════════════════════════════════════════════════
# 4. Purchase Order
# ═══════════════════════════════════════════════════

class POLineSerializer(serializers.ModelSerializer):
    class Meta:
        model = PurchaseOrderLineModel
        fields = [
            "id", "order", "line_number",
            "item_id", "item_code", "item_name", "description",
            "quantity", "received_quantity", "returned_quantity",
            "uom_id", "uom_code",
            "unit_price", "discount_percent", "discount_amount",
            "tax_percent", "tax_amount", "line_total",
            "warehouse_id", "warehouse_name",
            "required_date", "notes",
            "pr_line_id", "rfq_response_line_id",
        ]
        read_only_fields = [
            "id", "order", "received_quantity", "returned_quantity",
            "discount_amount", "tax_amount", "line_total",
        ]


class POSerializer(serializers.ModelSerializer):
    lines = POLineSerializer(many=True, read_only=True)
    vendor_id = serializers.UUIDField(required=False, allow_null=True)
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")
    vendor_code = serializers.CharField(source="vendor.vendor_code", read_only=True, default="")

    class Meta:
        model = PurchaseOrderModel
        fields = [
            "id", "po_number", "title", "description",
            "status", "priority",
            "vendor_id", "vendor_name", "vendor_code",
            "pr_id", "pr_number", "rfq_id", "rfq_number",
            "contract_id",
            "buyer_id", "buyer_name",
            "order_date", "expected_delivery_date", "actual_delivery_date",
            "subtotal", "total_discount", "total_tax", "total_amount",
            "currency_code",
            "payment_terms", "delivery_terms", "shipping_address",
            "approved_by_id", "approved_at", "rejection_reason",
            "notes", "lines",
            "created_at", "updated_at",
        ]
        read_only_fields = [
            "id", "status",
            "subtotal", "total_discount", "total_tax", "total_amount",
            "approved_by_id", "approved_at", "rejection_reason",
            "created_at", "updated_at",
        ]


class POListSerializer(serializers.ModelSerializer):
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = PurchaseOrderModel
        fields = [
            "id", "po_number", "title", "status", "priority",
            "vendor_name", "total_amount", "order_date",
            "expected_delivery_date", "created_at",
        ]


class POCreateSerializer(serializers.ModelSerializer):
    vendor_id = serializers.UUIDField(required=False, allow_null=True)
    lines = POLineSerializer(many=True)

    class Meta:
        model = PurchaseOrderModel
        fields = [
            "po_number", "title", "description", "priority",
            "vendor_id",
            "pr_id", "pr_number", "rfq_id", "rfq_number",
            "contract_id",
            "buyer_id", "buyer_name",
            "expected_delivery_date", "currency_code",
            "payment_terms", "delivery_terms", "shipping_address",
            "notes", "lines",
        ]

    def create(self, validated_data):
        lines_data = validated_data.pop("lines", [])
        po = PurchaseOrderModel.objects.create(**validated_data)
        subtotal = 0
        total_discount = 0
        total_tax = 0
        for idx, line_data in enumerate(lines_data, start=1):
            line_data["line_number"] = idx
            line_data["order"] = po
            if "tenant" not in line_data and hasattr(po, "tenant"):
                line_data["tenant"] = po.tenant
            # Calculate line totals
            qty = line_data.get("quantity", 0)
            price = line_data.get("unit_price", 0)
            disc_pct = line_data.get("discount_percent", 0)
            tax_pct = line_data.get("tax_percent", 0)
            line_sub = qty * price
            disc_amt = line_sub * disc_pct / 100 if disc_pct else 0
            net = line_sub - disc_amt
            tax_amt = net * tax_pct / 100 if tax_pct else 0
            line_data["discount_amount"] = disc_amt
            line_data["tax_amount"] = tax_amt
            line_data["line_total"] = net + tax_amt
            subtotal += line_sub
            total_discount += disc_amt
            total_tax += tax_amt
            PurchaseOrderLineModel.objects.create(**line_data)
        po.subtotal = subtotal
        po.total_discount = total_discount
        po.total_tax = total_tax
        po.total_amount = subtotal - total_discount + total_tax
        po.save(update_fields=["subtotal", "total_discount", "total_tax", "total_amount"])
        return po


class PORejectSerializer(serializers.Serializer):
    reason = serializers.CharField(required=False, allow_blank=True)


# ═══════════════════════════════════════════════════
# 5. Goods Receipt
# ═══════════════════════════════════════════════════

class GRLineSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsReceiptLineModel
        fields = [
            "id", "receipt", "line_number", "po_line_id",
            "item_id", "item_code", "item_name",
            "ordered_quantity", "received_quantity",
            "accepted_quantity", "rejected_quantity",
            "uom_id", "uom_code",
            "unit_cost", "line_total",
            "warehouse_id", "warehouse_name", "storage_location_id",
            "batch_number", "serial_numbers",
            "inspection_required", "notes",
        ]
        read_only_fields = ["id", "receipt", "line_total"]


class GRSerializer(serializers.ModelSerializer):
    lines = GRLineSerializer(many=True, read_only=True)
    po_id = serializers.UUIDField(required=False, allow_null=True)
    po_number = serializers.CharField(source="po.po_number", read_only=True, default="")
    vendor_id = serializers.UUIDField(required=False, allow_null=True)
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = GoodsReceiptModel
        fields = [
            "id", "gr_number", "status",
            "po_id", "po_number",
            "vendor_id", "vendor_name",
            "receiver_id", "receiver_name",
            "receipt_date", "posting_date",
            "total_amount", "currency_code",
            "delivery_note_number", "transporter",
            "notes", "lines",
            "created_at", "updated_at",
        ]
        read_only_fields = [
            "id", "status", "total_amount",
            "created_at", "updated_at",
        ]


class GRListSerializer(serializers.ModelSerializer):
    po_number = serializers.CharField(source="po.po_number", read_only=True, default="")
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = GoodsReceiptModel
        fields = [
            "id", "gr_number", "status",
            "po_number", "vendor_name",
            "receipt_date", "total_amount",
            "created_at",
        ]


class GRCreateSerializer(serializers.ModelSerializer):
    po_id = serializers.UUIDField(required=False, allow_null=True)
    vendor_id = serializers.UUIDField(required=False, allow_null=True)
    lines = GRLineSerializer(many=True)

    class Meta:
        model = GoodsReceiptModel
        fields = [
            "gr_number", "po_id",
            "vendor_id",
            "receiver_id", "receiver_name",
            "receipt_date", "delivery_note_number", "transporter",
            "currency_code", "notes", "lines",
        ]

    def create(self, validated_data):
        lines_data = validated_data.pop("lines", [])
        gr = GoodsReceiptModel.objects.create(**validated_data)
        total = 0
        for idx, line_data in enumerate(lines_data, start=1):
            line_data["line_number"] = idx
            line_data["receipt"] = gr
            if "tenant" not in line_data and hasattr(gr, "tenant"):
                line_data["tenant"] = gr.tenant
            line_total = (line_data.get("accepted_quantity", 0)) * (line_data.get("unit_cost", 0))
            line_data["line_total"] = line_total
            total += line_total
            GoodsReceiptLineModel.objects.create(**line_data)
        gr.total_amount = total
        gr.save(update_fields=["total_amount"])
        return gr


# ═══════════════════════════════════════════════════
# 6. Purchase Return
# ═══════════════════════════════════════════════════

class ReturnLineSerializer(serializers.ModelSerializer):
    class Meta:
        model = PurchaseReturnLineModel
        fields = [
            "id", "purchase_return", "line_number",
            "gr_line_id", "po_line_id",
            "item_id", "item_code", "item_name",
            "return_quantity", "uom_id", "uom_code",
            "unit_cost", "line_total",
            "reason", "reason_detail",
            "warehouse_id", "batch_number", "serial_numbers",
            "notes",
        ]
        read_only_fields = ["id", "line_total"]


class ReturnSerializer(serializers.ModelSerializer):
    lines = ReturnLineSerializer(many=True, read_only=True)
    po_id = serializers.UUIDField(required=False, allow_null=True)
    po_number = serializers.CharField(source="po.po_number", read_only=True, default="")
    gr_id = serializers.UUIDField(required=False, allow_null=True)
    gr_number = serializers.CharField(source="gr.gr_number", read_only=True, default="")
    vendor_id = serializers.UUIDField(required=False, allow_null=True)
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = PurchaseReturnModel
        fields = [
            "id", "return_number", "status",
            "po_id", "po_number",
            "gr_id", "gr_number",
            "vendor_id", "vendor_name",
            "requester_id", "requester_name",
            "return_date", "total_amount", "currency_code",
            "approved_by_id", "approved_at",
            "notes", "lines",
            "created_at", "updated_at",
        ]
        read_only_fields = [
            "id", "status", "total_amount",
            "approved_by_id", "approved_at",
            "created_at", "updated_at",
        ]


class ReturnListSerializer(serializers.ModelSerializer):
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = PurchaseReturnModel
        fields = [
            "id", "return_number", "status",
            "vendor_name", "total_amount",
            "return_date", "created_at",
        ]


# ═══════════════════════════════════════════════════
# 7. Vendor Evaluation
# ═══════════════════════════════════════════════════

class EvaluationCriteriaSerializer(serializers.ModelSerializer):
    class Meta:
        model = EvaluationCriteriaModel
        fields = [
            "id", "criteria_code", "criteria_name",
            "description", "weight", "max_score",
            "is_active", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class EvaluationPeriodSerializer(serializers.ModelSerializer):
    class Meta:
        model = EvaluationPeriodModel
        fields = [
            "id", "period_name", "start_date", "end_date",
            "is_active", "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class EvaluationScoreSerializer(serializers.ModelSerializer):
    criteria_name = serializers.CharField(source="criteria.criteria_name", read_only=True, default="")

    class Meta:
        model = VendorEvaluationScoreModel
        fields = [
            "id", "evaluation", "criteria",
            "criteria_name", "weight",
            "score", "weighted_score", "comments",
        ]
        read_only_fields = ["id", "evaluation", "weighted_score"]


class EvaluationSerializer(serializers.ModelSerializer):
    scores = EvaluationScoreSerializer(many=True, read_only=True)
    vendor_id = serializers.UUIDField()
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")
    period_id = serializers.UUIDField()
    period_name = serializers.CharField(source="period.period_name", read_only=True, default="")

    class Meta:
        model = VendorEvaluationModel
        fields = [
            "id", "vendor_id", "vendor_name",
            "period_id", "period_name",
            "evaluator_id", "evaluator_name",
            "status", "evaluation_date",
            "total_score", "rating",
            "comments", "scores",
            "created_at", "updated_at",
        ]
        read_only_fields = [
            "id", "status", "total_score", "rating",
            "created_at", "updated_at",
        ]


class EvaluationListSerializer(serializers.ModelSerializer):
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")
    period_name = serializers.CharField(source="period.period_name", read_only=True, default="")

    class Meta:
        model = VendorEvaluationModel
        fields = [
            "id", "vendor_name", "period_name",
            "status", "total_score", "rating",
            "evaluation_date", "created_at",
        ]


# ═══════════════════════════════════════════════════
# 8. Price Management
# ═══════════════════════════════════════════════════

class PriceListItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorPriceListItemModel
        fields = [
            "id", "price_list",
            "item_id", "item_code", "item_name",
            "uom_id", "uom_code",
            "unit_price", "min_quantity", "lead_time_days",
            "notes", "is_active",
        ]
        read_only_fields = ["id", "price_list"]


class PriceListSerializer(serializers.ModelSerializer):
    items = PriceListItemSerializer(many=True, read_only=True)
    vendor_id = serializers.UUIDField()
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = VendorPriceListModel
        fields = [
            "id", "vendor_id", "vendor_name",
            "price_list_name", "description",
            "currency_code",
            "valid_from", "valid_to",
            "is_active", "items",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]


class PriceListListSerializer(serializers.ModelSerializer):
    vendor_name = serializers.CharField(source="vendor.vendor_name", read_only=True, default="")

    class Meta:
        model = VendorPriceListModel
        fields = [
            "id", "vendor_name", "price_list_name",
            "valid_from", "valid_to", "is_active",
        ]


class DiscountSerializer(serializers.ModelSerializer):
    vendor_id = serializers.UUIDField(required=False, allow_null=True)

    class Meta:
        model = PurchaseDiscountModel
        fields = [
            "id", "vendor_id", "item_id", "item_group_id",
            "discount_type", "discount_value",
            "min_quantity", "min_amount",
            "valid_from", "valid_to",
            "description", "is_active",
            "created_at", "updated_at",
        ]
        read_only_fields = ["id", "created_at", "updated_at"]
