from rest_framework import serializers

from shop_management.models.data.warehouse_transfer import WarehouseTransfer, WarehouseTransferItem
from shop_management.serializers.data.base import DataRootSerializer
from account.permissions import assert_shop_access, assert_warehouse_access


class WarehouseTransferItemSerializer(DataRootSerializer):
    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="cost_currency.title", read_only=True)

    class Meta:
        model = WarehouseTransferItem
        fields = ["id", "product", "product_name", "batch", "batch_number", "quantity", "unit_cost_snapshot", "cost_currency", "currency_title", "created_at"]
        read_only_fields = ["id", "unit_cost_snapshot", "cost_currency", "created_at"]


class WarehouseTransferSerializer(DataRootSerializer):
    items = WarehouseTransferItemSerializer(many=True)
    shop_name = serializers.CharField(source="shop.name", read_only=True)
    source_warehouse_name = serializers.CharField(source="source_warehouse.name", read_only=True)
    destination_warehouse_name = serializers.CharField(source="destination_warehouse.name", read_only=True)

    class Meta:
        model = WarehouseTransfer
        fields = "__all__"
        read_only_fields = ["transfer_number", "status", "dispatched_at", "dispatched_by", "received_at", "received_by", "voided_at", "voided_by", "void_reason", "created_by"]

    def validate(self, attrs):
        shop = attrs.get("shop", getattr(self.instance, "shop", None))
        source = attrs.get("source_warehouse", getattr(self.instance, "source_warehouse", None))
        destination = attrs.get("destination_warehouse", getattr(self.instance, "destination_warehouse", None))
        request = self.context.get("request")
        if request and shop:
            shop = assert_shop_access(request.user, shop, request)
        if request and source:
            source = assert_warehouse_access(request.user, source, request, active_only=True)
        if request and destination:
            destination = assert_warehouse_access(request.user, destination, request, active_only=True)
        if source and destination and source.pk == destination.pk:
            raise serializers.ValidationError({"destination_warehouse": "Choose a different destination warehouse."})
        if shop and ((source and source.shop_id != shop.id) or (destination and destination.shop_id != shop.id)):
            raise serializers.ValidationError({"warehouses": "Both warehouses must belong to the selected branch."})
        return attrs

    def create(self, validated_data):
        items = validated_data.pop("items")
        user = self.context["request"].user
        document = WarehouseTransfer.objects.create(created_by=user, **validated_data)
        for item in items:
            item.pop("created_by", None)
            WarehouseTransferItem.objects.create(transfer=document, created_by=user, **item)
        return document

    def update(self, instance, validated_data):
        items = validated_data.pop("items", None)
        for field, value in validated_data.items():
            setattr(instance, field, value)
        instance.save()
        if items is not None:
            instance.items.all().delete()
            for item in items:
                item.pop("created_by", None)
                WarehouseTransferItem.objects.create(transfer=instance, created_by=self.context["request"].user, **item)
        return instance
