from rest_framework import serializers

from shop_management.models.data.inventory import (
    InventoryBatch,
    StockBalance,
    StockMovement,
)
from shop_management.serializers.data.base import DataRootSerializer


class InventoryBatchSerializer(DataRootSerializer):
    product_details = serializers.SerializerMethodField()
    is_expired = serializers.BooleanField(read_only=True)

    class Meta:
        model = InventoryBatch
        fields = "__all__"
        read_only_fields = ("created_by",)

    def get_product_details(self, obj):
        return {"id": obj.product_id, "name": obj.product.name, "code": obj.product.code}

    def validate(self, attrs):
        product = attrs.get("product") or getattr(self.instance, "product", None)
        expiry = attrs.get("expiry_date", getattr(self.instance, "expiry_date", None))
        manufacture = attrs.get(
            "manufacture_date", getattr(self.instance, "manufacture_date", None)
        )
        if manufacture and expiry and expiry < manufacture:
            raise serializers.ValidationError(
                {"expiry_date": "Expiry date cannot be before manufacture date."}
            )
        if product and product.requires_expiry and not expiry:
            raise serializers.ValidationError(
                {"expiry_date": "This product requires an expiry date."}
            )
        request = self.context.get("request")
        if request and product and not request.user.is_superuser:
            allowed = product.shop.owner_id == request.user.id or product.shop.assigned_users.filter(
                pk=request.user.id
            ).exists()
            if not allowed:
                raise serializers.ValidationError(
                    {"product": "You do not have access to this product branch."}
                )
        return attrs


class StockBalanceSerializer(DataRootSerializer):
    warehouse_details = serializers.SerializerMethodField()
    product_details = serializers.SerializerMethodField()
    batch_details = serializers.SerializerMethodField()
    currency_details = serializers.SerializerMethodField()

    class Meta:
        model = StockBalance
        fields = "__all__"

    def get_warehouse_details(self, obj):
        return {"id": obj.warehouse_id, "code": obj.warehouse.code, "name": obj.warehouse.name}

    def get_product_details(self, obj):
        default_unit = obj.product.default_unit
        posted_items = getattr(obj.product, "posted_purchase_items_for_pricing", None)
        if posted_items is None:
            posted_items = obj.product.purchase_items.filter(
                purchase__document_status="POSTED",
            ).select_related("purchase__currency").order_by("-purchase__purchase_date", "-id")
        latest_purchase_item = next(
            (item for item in posted_items if item.purchase.currency_id == obj.cost_currency_id),
            None,
        )
        return {
            "id": obj.product_id,
            "name": obj.product.name,
            "code": obj.product.code,
            "default_unit": obj.product.default_unit_id,
            "default_unit_details": (
                {"id": default_unit.id, "title": default_unit.title}
                if default_unit else None
            ),
            "prices": [
                {
                    "id": price.id,
                    "currency": price.currency_id,
                    "currency_title": price.currency.title,
                    "price_type": price.price_type,
                    "amount": str(price.amount),
                }
                for price in obj.product.prices.all()
            ],
            "latest_purchase_prices": (
                {
                    "currency": latest_purchase_item.purchase.currency_id,
                    "currency_title": latest_purchase_item.purchase.currency.title,
                    "wholesale_price": str(latest_purchase_item.wholesale_price) if latest_purchase_item.wholesale_price is not None else None,
                    "retail_price": str(latest_purchase_item.retail_price) if latest_purchase_item.retail_price is not None else None,
                }
                if latest_purchase_item else None
            ),
        }

    def get_batch_details(self, obj):
        return {
            "id": obj.batch_id, "batch_number": obj.batch.batch_number,
            "expiry_date": obj.batch.expiry_date, "is_blocked": obj.batch.is_blocked,
            "is_expired": obj.batch.is_expired,
        }

    def get_currency_details(self, obj):
        return {"id": obj.cost_currency_id, "title": obj.cost_currency.title}


class StockMovementSerializer(DataRootSerializer):
    warehouse_name = serializers.CharField(source="warehouse.name", read_only=True)
    product_name = serializers.CharField(source="product.name", read_only=True)
    batch_number = serializers.CharField(source="batch.batch_number", read_only=True)
    currency_title = serializers.CharField(source="currency.title", read_only=True)
    movement_type_display = serializers.CharField(
        source="get_movement_type_display", read_only=True
    )

    class Meta:
        model = StockMovement
        fields = "__all__"
        read_only_fields = fields
