"""
SCM Entity-Model Mappers.

تبدیل بین Domain Entities و ORM Models.
"""
from decimal import Decimal
from typing import Optional

from ..persistence.models import (
    VendorCategoryModel,
    VendorModel,
    VendorContactModel,
    VendorBankAccountModel,
    VendorAddressModel,
)
from ..persistence.models_extended import (
    PurchaseRequisitionModel,
    PurchaseRequisitionLineModel,
    RFQModel,
    RFQLineModel,
    RFQVendorResponseModel,
    RFQVendorResponseLineModel,
    PurchaseOrderModel,
    PurchaseOrderLineModel,
    GoodsReceiptModel,
    GoodsReceiptLineModel,
    PurchaseReturnModel,
    PurchaseReturnLineModel,
    VendorEvaluationModel,
    VendorEvaluationScoreModel,
    EvaluationCriteriaModel,
    EvaluationPeriodModel,
    VendorPriceListModel,
    VendorPriceListItemModel,
    PurchaseDiscountModel,
)
from ...domain.entities.vendor import (
    Vendor, VendorCategory, VendorContact, VendorBankAccount,
    VendorAddress, VendorStatus, VendorType, AddressType,
)
from ...domain.entities.purchase_requisition import (
    PurchaseRequisition, PurchaseRequisitionLine, PRStatus, PRPriority,
)
from ...domain.entities.rfq import (
    RFQ, RFQLine, RFQVendorResponse, RFQVendorResponseLine,
    RFQStatus, RFQResponseStatus,
)
from ...domain.entities.purchase_order import (
    PurchaseOrder, PurchaseOrderLine, POStatus, POPriority,
)
from ...domain.entities.goods_receipt import (
    GoodsReceipt, GoodsReceiptLine, GRStatus,
)
from ...domain.entities.purchase_return import (
    PurchaseReturn, PurchaseReturnLine, ReturnStatus, ReturnReason,
)
from ...domain.entities.vendor_evaluation import (
    VendorEvaluation, VendorEvaluationScore,
    EvaluationCriteria, EvaluationPeriod,
    EvaluationStatus, EvaluationRating,
)
from ...domain.entities.price_management import (
    VendorPriceList, VendorPriceListItem, PurchaseDiscount, DiscountType,
)


# ═══════════════════════════════════════════════════
# Vendor Mappers
# ═══════════════════════════════════════════════════

class VendorCategoryMapper:
    @staticmethod
    def to_entity(model: VendorCategoryModel) -> VendorCategory:
        return VendorCategory(
            id=model.id,
            tenant_id=model.tenant_id,
            category_code=model.category_code,
            category_name=model.category_name,
            parent_category_id=model.parent_category_id,
            level=model.level,
            description=model.description,
            is_active=model.is_active,
            created_at=model.created_at,
            updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: VendorCategory, model: Optional[VendorCategoryModel] = None) -> VendorCategoryModel:
        if model is None:
            model = VendorCategoryModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.category_code = entity.category_code
        model.category_name = entity.category_name
        model.parent_category_id = entity.parent_category_id
        model.level = entity.level
        model.description = entity.description
        model.is_active = entity.is_active
        return model


class VendorMapper:
    @staticmethod
    def to_entity(model: VendorModel) -> Vendor:
        return Vendor(
            id=model.id,
            tenant_id=model.tenant_id,
            vendor_code=model.vendor_code,
            vendor_name=model.vendor_name,
            vendor_name_en=model.vendor_name_en,
            vendor_type=VendorType(model.vendor_type) if model.vendor_type else VendorType.COMPANY,
            category_id=model.category_id,
            status=VendorStatus(model.status) if model.status else VendorStatus.PENDING_APPROVAL,
            national_id=model.national_id,
            economic_code=model.economic_code,
            registration_number=model.registration_number,
            phone=model.phone,
            fax=model.fax,
            email=model.email,
            website=model.website,
            representative_employee_id=model.representative_employee_id,
            payment_terms_days=model.payment_terms_days,
            credit_limit=model.credit_limit,
            currency_code=model.currency_code,
            notes=model.notes,
            is_active=model.is_active,
            created_at=model.created_at,
            updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: Vendor, model: Optional[VendorModel] = None) -> VendorModel:
        if model is None:
            model = VendorModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.vendor_code = entity.vendor_code
        model.vendor_name = entity.vendor_name
        model.vendor_name_en = entity.vendor_name_en
        model.vendor_type = entity.vendor_type.value if entity.vendor_type else "COMPANY"
        model.category_id = entity.category_id
        model.status = entity.status.value if entity.status else "PENDING_APPROVAL"
        model.national_id = entity.national_id
        model.economic_code = entity.economic_code
        model.registration_number = entity.registration_number
        model.phone = entity.phone
        model.fax = entity.fax
        model.email = entity.email
        model.website = entity.website
        model.representative_employee_id = entity.representative_employee_id
        model.payment_terms_days = entity.payment_terms_days
        model.credit_limit = entity.credit_limit
        model.currency_code = entity.currency_code
        model.notes = entity.notes
        model.is_active = entity.is_active
        return model


class VendorContactMapper:
    @staticmethod
    def to_entity(model: VendorContactModel) -> VendorContact:
        return VendorContact(
            id=model.id, tenant_id=model.tenant_id,
            vendor_id=model.vendor_id,
            contact_name=model.contact_name, contact_title=model.contact_title,
            phone=model.phone, mobile=model.mobile, email=model.email,
            is_primary=model.is_primary, is_active=model.is_active,
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: VendorContact, model=None) -> VendorContactModel:
        if model is None:
            model = VendorContactModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.vendor_id = entity.vendor_id
        model.contact_name = entity.contact_name
        model.contact_title = entity.contact_title
        model.phone = entity.phone
        model.mobile = entity.mobile
        model.email = entity.email
        model.is_primary = entity.is_primary
        model.is_active = entity.is_active
        return model


class VendorBankAccountMapper:
    @staticmethod
    def to_entity(model: VendorBankAccountModel) -> VendorBankAccount:
        return VendorBankAccount(
            id=model.id, tenant_id=model.tenant_id,
            vendor_id=model.vendor_id,
            bank_name=model.bank_name, branch_name=model.branch_name,
            account_number=model.account_number, iban=model.iban,
            account_holder_name=model.account_holder_name,
            is_default=model.is_default, is_active=model.is_active,
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: VendorBankAccount, model=None) -> VendorBankAccountModel:
        if model is None:
            model = VendorBankAccountModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.vendor_id = entity.vendor_id
        model.bank_name = entity.bank_name
        model.branch_name = entity.branch_name
        model.account_number = entity.account_number
        model.iban = entity.iban
        model.account_holder_name = entity.account_holder_name
        model.is_default = entity.is_default
        model.is_active = entity.is_active
        return model


class VendorAddressMapper:
    @staticmethod
    def to_entity(model: VendorAddressModel) -> VendorAddress:
        return VendorAddress(
            id=model.id, tenant_id=model.tenant_id,
            vendor_id=model.vendor_id,
            address_type=AddressType(model.address_type) if model.address_type else AddressType.MAIN,
            address_line1=model.address_line1, address_line2=model.address_line2,
            city=model.city, province=model.province,
            postal_code=model.postal_code, country=model.country,
            phone=model.phone, fax=model.fax,
            is_default=model.is_default,
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: VendorAddress, model=None) -> VendorAddressModel:
        if model is None:
            model = VendorAddressModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.vendor_id = entity.vendor_id
        model.address_type = entity.address_type.value if entity.address_type else "MAIN"
        model.address_line1 = entity.address_line1
        model.address_line2 = entity.address_line2
        model.city = entity.city
        model.province = entity.province
        model.postal_code = entity.postal_code
        model.country = entity.country
        model.phone = entity.phone
        model.fax = entity.fax
        model.is_default = entity.is_default
        return model


# ═══════════════════════════════════════════════════
# Purchase Requisition Mappers
# ═══════════════════════════════════════════════════

class PRLineMapper:
    @staticmethod
    def to_entity(model: PurchaseRequisitionLineModel) -> PurchaseRequisitionLine:
        return PurchaseRequisitionLine(
            id=model.id, tenant_id=model.tenant_id,
            requisition_id=model.requisition_id,
            line_number=model.line_number,
            item_id=model.item_id, item_code=model.item_code, item_name=model.item_name,
            description=model.description,
            quantity=model.quantity, uom_id=model.uom_id, uom_code=model.uom_code,
            estimated_unit_price=model.estimated_unit_price,
            estimated_total_price=model.estimated_total_price,
            required_date=model.required_date,
            warehouse_id=model.warehouse_id, warehouse_name=model.warehouse_name,
            preferred_vendor_id=model.preferred_vendor_id,
            notes=model.notes, is_converted=model.is_converted,
            converted_po_id=model.converted_po_id,
        )

    @staticmethod
    def to_model(entity: PurchaseRequisitionLine, model=None) -> PurchaseRequisitionLineModel:
        if model is None:
            model = PurchaseRequisitionLineModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.requisition_id = entity.requisition_id
        model.line_number = entity.line_number
        model.item_id = entity.item_id
        model.item_code = entity.item_code
        model.item_name = entity.item_name
        model.description = entity.description
        model.quantity = entity.quantity
        model.uom_id = entity.uom_id
        model.uom_code = entity.uom_code
        model.estimated_unit_price = entity.estimated_unit_price
        model.estimated_total_price = entity.estimated_total_price
        model.required_date = entity.required_date
        model.warehouse_id = entity.warehouse_id
        model.warehouse_name = entity.warehouse_name
        model.preferred_vendor_id = entity.preferred_vendor_id
        model.notes = entity.notes
        model.is_converted = entity.is_converted
        model.converted_po_id = entity.converted_po_id
        return model


class PRMapper:
    @staticmethod
    def to_entity(model: PurchaseRequisitionModel, lines=None) -> PurchaseRequisition:
        return PurchaseRequisition(
            id=model.id, tenant_id=model.tenant_id,
            pr_number=model.pr_number, title=model.title, description=model.description,
            status=PRStatus(model.status) if model.status else PRStatus.DRAFT,
            priority=PRPriority(model.priority) if model.priority else PRPriority.NORMAL,
            requester_id=model.requester_id, requester_name=model.requester_name,
            department=model.department,
            request_date=model.request_date, required_date=model.required_date,
            total_estimated_amount=model.total_estimated_amount,
            currency_code=model.currency_code,
            approved_by_id=model.approved_by_id, approved_at=model.approved_at,
            rejection_reason=model.rejection_reason,
            notes=model.notes,
            lines=lines or [],
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: PurchaseRequisition, model=None) -> PurchaseRequisitionModel:
        if model is None:
            model = PurchaseRequisitionModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.pr_number = entity.pr_number
        model.title = entity.title
        model.description = entity.description
        model.status = entity.status.value if entity.status else "DRAFT"
        model.priority = entity.priority.value if entity.priority else "NORMAL"
        model.requester_id = entity.requester_id
        model.requester_name = entity.requester_name
        model.department = entity.department
        model.request_date = entity.request_date
        model.required_date = entity.required_date
        model.total_estimated_amount = entity.total_estimated_amount
        model.currency_code = entity.currency_code
        model.approved_by_id = entity.approved_by_id
        model.approved_at = entity.approved_at
        model.rejection_reason = entity.rejection_reason
        model.notes = entity.notes
        return model


# ═══════════════════════════════════════════════════
# Purchase Order Mappers
# ═══════════════════════════════════════════════════

class POLineMapper:
    @staticmethod
    def to_entity(model: PurchaseOrderLineModel) -> PurchaseOrderLine:
        return PurchaseOrderLine(
            id=model.id, tenant_id=model.tenant_id,
            order_id=model.order_id,
            line_number=model.line_number,
            item_id=model.item_id, item_code=model.item_code, item_name=model.item_name,
            description=model.description,
            quantity=model.quantity,
            received_quantity=model.received_quantity,
            returned_quantity=model.returned_quantity,
            uom_id=model.uom_id, uom_code=model.uom_code,
            unit_price=model.unit_price,
            discount_percent=model.discount_percent,
            discount_amount=model.discount_amount,
            tax_percent=model.tax_percent,
            tax_amount=model.tax_amount,
            line_total=model.line_total,
            warehouse_id=model.warehouse_id, warehouse_name=model.warehouse_name,
            required_date=model.required_date, notes=model.notes,
            pr_line_id=model.pr_line_id,
            rfq_response_line_id=model.rfq_response_line_id,
        )

    @staticmethod
    def to_model(entity: PurchaseOrderLine, model=None) -> PurchaseOrderLineModel:
        if model is None:
            model = PurchaseOrderLineModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.order_id = entity.order_id
        model.line_number = entity.line_number
        model.item_id = entity.item_id
        model.item_code = entity.item_code
        model.item_name = entity.item_name
        model.description = entity.description
        model.quantity = entity.quantity
        model.received_quantity = entity.received_quantity
        model.returned_quantity = entity.returned_quantity
        model.uom_id = entity.uom_id
        model.uom_code = entity.uom_code
        model.unit_price = entity.unit_price
        model.discount_percent = entity.discount_percent
        model.discount_amount = entity.discount_amount
        model.tax_percent = entity.tax_percent
        model.tax_amount = entity.tax_amount
        model.line_total = entity.line_total
        model.warehouse_id = entity.warehouse_id
        model.warehouse_name = entity.warehouse_name
        model.required_date = entity.required_date
        model.notes = entity.notes
        model.pr_line_id = entity.pr_line_id
        model.rfq_response_line_id = entity.rfq_response_line_id
        return model


class POMapper:
    @staticmethod
    def to_entity(model: PurchaseOrderModel, lines=None) -> PurchaseOrder:
        return PurchaseOrder(
            id=model.id, tenant_id=model.tenant_id,
            po_number=model.po_number, title=model.title, description=model.description,
            status=POStatus(model.status) if model.status else POStatus.DRAFT,
            priority=POPriority(model.priority) if model.priority else POPriority.NORMAL,
            vendor_id=model.vendor_id, vendor_name=model.vendor_name, vendor_code=model.vendor_code,
            pr_id=model.pr_id, pr_number=model.pr_number,
            rfq_id=model.rfq_id, rfq_number=model.rfq_number,
            contract_id=model.contract_id,
            buyer_id=model.buyer_id, buyer_name=model.buyer_name,
            order_date=model.order_date,
            expected_delivery_date=model.expected_delivery_date,
            actual_delivery_date=model.actual_delivery_date,
            subtotal=model.subtotal, total_discount=model.total_discount,
            total_tax=model.total_tax, total_amount=model.total_amount,
            currency_code=model.currency_code,
            payment_terms=model.payment_terms, delivery_terms=model.delivery_terms,
            shipping_address=model.shipping_address,
            approved_by_id=model.approved_by_id, approved_at=model.approved_at,
            rejection_reason=model.rejection_reason,
            notes=model.notes,
            lines=lines or [],
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: PurchaseOrder, model=None) -> PurchaseOrderModel:
        if model is None:
            model = PurchaseOrderModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.po_number = entity.po_number
        model.title = entity.title
        model.description = entity.description
        model.status = entity.status.value if entity.status else "DRAFT"
        model.priority = entity.priority.value if entity.priority else "NORMAL"
        model.vendor_id = entity.vendor_id
        model.vendor_name = entity.vendor_name
        model.vendor_code = entity.vendor_code
        model.pr_id = entity.pr_id
        model.pr_number = entity.pr_number
        model.rfq_id = entity.rfq_id
        model.rfq_number = entity.rfq_number
        model.contract_id = entity.contract_id
        model.buyer_id = entity.buyer_id
        model.buyer_name = entity.buyer_name
        model.order_date = entity.order_date
        model.expected_delivery_date = entity.expected_delivery_date
        model.actual_delivery_date = entity.actual_delivery_date
        model.subtotal = entity.subtotal
        model.total_discount = entity.total_discount
        model.total_tax = entity.total_tax
        model.total_amount = entity.total_amount
        model.currency_code = entity.currency_code
        model.payment_terms = entity.payment_terms
        model.delivery_terms = entity.delivery_terms
        model.shipping_address = entity.shipping_address
        model.approved_by_id = entity.approved_by_id
        model.approved_at = entity.approved_at
        model.rejection_reason = entity.rejection_reason
        model.notes = entity.notes
        return model


# ═══════════════════════════════════════════════════
# Goods Receipt Mappers
# ═══════════════════════════════════════════════════

class GRLineMapper:
    @staticmethod
    def to_entity(model: GoodsReceiptLineModel) -> GoodsReceiptLine:
        return GoodsReceiptLine(
            id=model.id, tenant_id=model.tenant_id,
            receipt_id=model.receipt_id, line_number=model.line_number,
            po_line_id=model.po_line_id,
            item_id=model.item_id, item_code=model.item_code, item_name=model.item_name,
            ordered_quantity=model.ordered_quantity,
            received_quantity=model.received_quantity,
            accepted_quantity=model.accepted_quantity,
            rejected_quantity=model.rejected_quantity,
            uom_id=model.uom_id, uom_code=model.uom_code,
            unit_cost=model.unit_cost, line_total=model.line_total,
            warehouse_id=model.warehouse_id, warehouse_name=model.warehouse_name,
            storage_location_id=model.storage_location_id,
            batch_number=model.batch_number,
            serial_numbers=model.serial_numbers or [],
            inspection_required=model.inspection_required,
            notes=model.notes,
        )

    @staticmethod
    def to_model(entity: GoodsReceiptLine, model=None) -> GoodsReceiptLineModel:
        if model is None:
            model = GoodsReceiptLineModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.receipt_id = entity.receipt_id
        model.line_number = entity.line_number
        model.po_line_id = entity.po_line_id
        model.item_id = entity.item_id
        model.item_code = entity.item_code
        model.item_name = entity.item_name
        model.ordered_quantity = entity.ordered_quantity
        model.received_quantity = entity.received_quantity
        model.accepted_quantity = entity.accepted_quantity
        model.rejected_quantity = entity.rejected_quantity
        model.uom_id = entity.uom_id
        model.uom_code = entity.uom_code
        model.unit_cost = entity.unit_cost
        model.line_total = entity.line_total
        model.warehouse_id = entity.warehouse_id
        model.warehouse_name = entity.warehouse_name
        model.storage_location_id = entity.storage_location_id
        model.batch_number = entity.batch_number
        model.serial_numbers = entity.serial_numbers
        model.inspection_required = entity.inspection_required
        model.notes = entity.notes
        return model


class GRMapper:
    @staticmethod
    def to_entity(model: GoodsReceiptModel, lines=None) -> GoodsReceipt:
        return GoodsReceipt(
            id=model.id, tenant_id=model.tenant_id,
            gr_number=model.gr_number,
            status=GRStatus(model.status) if model.status else GRStatus.DRAFT,
            po_id=model.po_id, po_number=model.po_number,
            vendor_id=model.vendor_id, vendor_name=model.vendor_name,
            receiver_id=model.receiver_id, receiver_name=model.receiver_name,
            receipt_date=model.receipt_date, posting_date=model.posting_date,
            total_amount=model.total_amount, currency_code=model.currency_code,
            delivery_note_number=model.delivery_note_number,
            transporter=model.transporter,
            notes=model.notes,
            lines=lines or [],
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: GoodsReceipt, model=None) -> GoodsReceiptModel:
        if model is None:
            model = GoodsReceiptModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.gr_number = entity.gr_number
        model.status = entity.status.value if entity.status else "DRAFT"
        model.po_id = entity.po_id
        model.po_number = entity.po_number
        model.vendor_id = entity.vendor_id
        model.vendor_name = entity.vendor_name
        model.receiver_id = entity.receiver_id
        model.receiver_name = entity.receiver_name
        model.receipt_date = entity.receipt_date
        model.posting_date = entity.posting_date
        model.total_amount = entity.total_amount
        model.currency_code = entity.currency_code
        model.delivery_note_number = entity.delivery_note_number
        model.transporter = entity.transporter
        model.notes = entity.notes
        return model


# ═══════════════════════════════════════════════════
# Purchase Return Mappers
# ═══════════════════════════════════════════════════

class ReturnLineMapper:
    @staticmethod
    def to_entity(model: PurchaseReturnLineModel) -> PurchaseReturnLine:
        return PurchaseReturnLine(
            id=model.id, tenant_id=model.tenant_id,
            return_id=model.purchase_return_id, line_number=model.line_number,
            gr_line_id=model.gr_line_id, po_line_id=model.po_line_id,
            item_id=model.item_id, item_code=model.item_code, item_name=model.item_name,
            return_quantity=model.return_quantity,
            uom_id=model.uom_id, uom_code=model.uom_code,
            unit_cost=model.unit_cost, line_total=model.line_total,
            reason=ReturnReason(model.reason) if model.reason else ReturnReason.OTHER,
            reason_detail=model.reason_detail,
            warehouse_id=model.warehouse_id,
            batch_number=model.batch_number,
            serial_numbers=model.serial_numbers or [],
            notes=model.notes,
        )

    @staticmethod
    def to_model(entity: PurchaseReturnLine, model=None) -> PurchaseReturnLineModel:
        if model is None:
            model = PurchaseReturnLineModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.purchase_return_id = entity.return_id
        model.line_number = entity.line_number
        model.gr_line_id = entity.gr_line_id
        model.po_line_id = entity.po_line_id
        model.item_id = entity.item_id
        model.item_code = entity.item_code
        model.item_name = entity.item_name
        model.return_quantity = entity.return_quantity
        model.uom_id = entity.uom_id
        model.uom_code = entity.uom_code
        model.unit_cost = entity.unit_cost
        model.line_total = entity.line_total
        model.reason = entity.reason.value if entity.reason else "OTHER"
        model.reason_detail = entity.reason_detail
        model.warehouse_id = entity.warehouse_id
        model.batch_number = entity.batch_number
        model.serial_numbers = entity.serial_numbers
        model.notes = entity.notes
        return model


class ReturnMapper:
    @staticmethod
    def to_entity(model: PurchaseReturnModel, lines=None) -> PurchaseReturn:
        return PurchaseReturn(
            id=model.id, tenant_id=model.tenant_id,
            return_number=model.return_number,
            status=ReturnStatus(model.status) if model.status else ReturnStatus.DRAFT,
            po_id=model.po_id, po_number=model.po_number,
            gr_id=model.gr_id, gr_number=model.gr_number,
            vendor_id=model.vendor_id, vendor_name=model.vendor_name,
            requester_id=model.requester_id, requester_name=model.requester_name,
            return_date=model.return_date,
            total_amount=model.total_amount, currency_code=model.currency_code,
            approved_by_id=model.approved_by_id, approved_at=model.approved_at,
            notes=model.notes,
            lines=lines or [],
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: PurchaseReturn, model=None) -> PurchaseReturnModel:
        if model is None:
            model = PurchaseReturnModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.return_number = entity.return_number
        model.status = entity.status.value if entity.status else "DRAFT"
        model.po_id = entity.po_id
        model.po_number = entity.po_number
        model.gr_id = entity.gr_id
        model.gr_number = entity.gr_number
        model.vendor_id = entity.vendor_id
        model.vendor_name = entity.vendor_name
        model.requester_id = entity.requester_id
        model.requester_name = entity.requester_name
        model.return_date = entity.return_date
        model.total_amount = entity.total_amount
        model.currency_code = entity.currency_code
        model.approved_by_id = entity.approved_by_id
        model.approved_at = entity.approved_at
        model.notes = entity.notes
        return model


# ═══════════════════════════════════════════════════
# Evaluation Mappers
# ═══════════════════════════════════════════════════

class EvaluationCriteriaMapper:
    @staticmethod
    def to_entity(model: EvaluationCriteriaModel) -> EvaluationCriteria:
        return EvaluationCriteria(
            id=model.id, tenant_id=model.tenant_id,
            criteria_code=model.criteria_code, criteria_name=model.criteria_name,
            description=model.description, weight=model.weight,
            max_score=model.max_score, is_active=model.is_active,
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: EvaluationCriteria, model=None) -> EvaluationCriteriaModel:
        if model is None:
            model = EvaluationCriteriaModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.criteria_code = entity.criteria_code
        model.criteria_name = entity.criteria_name
        model.description = entity.description
        model.weight = entity.weight
        model.max_score = entity.max_score
        model.is_active = entity.is_active
        return model


class EvaluationPeriodMapper:
    @staticmethod
    def to_entity(model: EvaluationPeriodModel) -> EvaluationPeriod:
        return EvaluationPeriod(
            id=model.id, tenant_id=model.tenant_id,
            period_name=model.period_name,
            start_date=model.start_date, end_date=model.end_date,
            is_active=model.is_active,
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: EvaluationPeriod, model=None) -> EvaluationPeriodModel:
        if model is None:
            model = EvaluationPeriodModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.period_name = entity.period_name
        model.start_date = entity.start_date
        model.end_date = entity.end_date
        model.is_active = entity.is_active
        return model


class EvaluationScoreMapper:
    @staticmethod
    def to_entity(model: VendorEvaluationScoreModel) -> VendorEvaluationScore:
        return VendorEvaluationScore(
            id=model.id, tenant_id=model.tenant_id,
            evaluation_id=model.evaluation_id,
            criteria_id=model.criteria_id,
            criteria_name=model.criteria_name,
            weight=model.weight, score=model.score,
            weighted_score=model.weighted_score,
            comments=model.comments,
        )

    @staticmethod
    def to_model(entity: VendorEvaluationScore, model=None) -> VendorEvaluationScoreModel:
        if model is None:
            model = VendorEvaluationScoreModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.evaluation_id = entity.evaluation_id
        model.criteria_id = entity.criteria_id
        model.criteria_name = entity.criteria_name
        model.weight = entity.weight
        model.score = entity.score
        model.weighted_score = entity.weighted_score
        model.comments = entity.comments
        return model


class EvaluationMapper:
    @staticmethod
    def to_entity(model: VendorEvaluationModel, scores=None) -> VendorEvaluation:
        return VendorEvaluation(
            id=model.id, tenant_id=model.tenant_id,
            vendor_id=model.vendor_id, vendor_name=model.vendor_name,
            period_id=model.period_id, period_name=model.period_name,
            evaluator_id=model.evaluator_id, evaluator_name=model.evaluator_name,
            status=EvaluationStatus(model.status) if model.status else EvaluationStatus.DRAFT,
            evaluation_date=model.evaluation_date,
            total_score=model.total_score,
            rating=EvaluationRating(model.rating) if model.rating else None,
            comments=model.comments,
            scores=scores or [],
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: VendorEvaluation, model=None) -> VendorEvaluationModel:
        if model is None:
            model = VendorEvaluationModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.vendor_id = entity.vendor_id
        model.vendor_name = entity.vendor_name
        model.period_id = entity.period_id
        model.period_name = entity.period_name
        model.evaluator_id = entity.evaluator_id
        model.evaluator_name = entity.evaluator_name
        model.status = entity.status.value if entity.status else "DRAFT"
        model.evaluation_date = entity.evaluation_date
        model.total_score = entity.total_score
        model.rating = entity.rating.value if entity.rating else ""
        model.comments = entity.comments
        return model


# ═══════════════════════════════════════════════════
# Price Management Mappers
# ═══════════════════════════════════════════════════

class PriceListItemMapper:
    @staticmethod
    def to_entity(model: VendorPriceListItemModel) -> VendorPriceListItem:
        return VendorPriceListItem(
            id=model.id, tenant_id=model.tenant_id,
            price_list_id=model.price_list_id,
            item_id=model.item_id, item_code=model.item_code, item_name=model.item_name,
            uom_id=model.uom_id, uom_code=model.uom_code,
            unit_price=model.unit_price, min_quantity=model.min_quantity,
            lead_time_days=model.lead_time_days, notes=model.notes,
            is_active=model.is_active,
        )

    @staticmethod
    def to_model(entity: VendorPriceListItem, model=None) -> VendorPriceListItemModel:
        if model is None:
            model = VendorPriceListItemModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.price_list_id = entity.price_list_id
        model.item_id = entity.item_id
        model.item_code = entity.item_code
        model.item_name = entity.item_name
        model.uom_id = entity.uom_id
        model.uom_code = entity.uom_code
        model.unit_price = entity.unit_price
        model.min_quantity = entity.min_quantity
        model.lead_time_days = entity.lead_time_days
        model.notes = entity.notes
        model.is_active = entity.is_active
        return model


class PriceListMapper:
    @staticmethod
    def to_entity(model: VendorPriceListModel, items=None) -> VendorPriceList:
        return VendorPriceList(
            id=model.id, tenant_id=model.tenant_id,
            vendor_id=model.vendor_id, vendor_name=model.vendor_name,
            price_list_name=model.price_list_name, description=model.description,
            currency_code=model.currency_code,
            valid_from=model.valid_from, valid_to=model.valid_to,
            is_active=model.is_active,
            items=items or [],
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: VendorPriceList, model=None) -> VendorPriceListModel:
        if model is None:
            model = VendorPriceListModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.vendor_id = entity.vendor_id
        model.vendor_name = entity.vendor_name
        model.price_list_name = entity.price_list_name
        model.description = entity.description
        model.currency_code = entity.currency_code
        model.valid_from = entity.valid_from
        model.valid_to = entity.valid_to
        model.is_active = entity.is_active
        return model


class DiscountMapper:
    @staticmethod
    def to_entity(model: PurchaseDiscountModel) -> PurchaseDiscount:
        return PurchaseDiscount(
            id=model.id, tenant_id=model.tenant_id,
            vendor_id=model.vendor_id,
            item_id=model.item_id, item_group_id=model.item_group_id,
            discount_type=DiscountType(model.discount_type) if model.discount_type else DiscountType.PERCENTAGE,
            discount_value=model.discount_value,
            min_quantity=model.min_quantity, min_amount=model.min_amount,
            valid_from=model.valid_from, valid_to=model.valid_to,
            description=model.description, is_active=model.is_active,
            created_at=model.created_at, updated_at=model.updated_at,
        )

    @staticmethod
    def to_model(entity: PurchaseDiscount, model=None) -> PurchaseDiscountModel:
        if model is None:
            model = PurchaseDiscountModel(id=entity.id)
        model.tenant_id = entity.tenant_id
        model.vendor_id = entity.vendor_id
        model.item_id = entity.item_id
        model.item_group_id = entity.item_group_id
        model.discount_type = entity.discount_type.value if entity.discount_type else "PERCENTAGE"
        model.discount_value = entity.discount_value
        model.min_quantity = entity.min_quantity
        model.min_amount = entity.min_amount
        model.valid_from = entity.valid_from
        model.valid_to = entity.valid_to
        model.description = entity.description
        model.is_active = entity.is_active
        return model
