from decimal import Decimal

from rest_framework import serializers

from inventory.models import SparePart

from .models import Sale, SaleItem, SaleReturn, SaleReturnItem


class SaleItemInputSerializer(serializers.Serializer):
    spare_part = serializers.PrimaryKeyRelatedField(queryset=SparePart.objects.all())
    quantity = serializers.IntegerField(min_value=1)
    unit_price = serializers.DecimalField(
        max_digits=15, decimal_places=2, min_value=Decimal('0'), required=False,
    )


class SaleItemSerializer(serializers.ModelSerializer):
    spare_part_name = serializers.CharField(source='spare_part.name', read_only=True)
    subtotal = serializers.DecimalField(max_digits=15, decimal_places=2, read_only=True)
    approved_by_name = serializers.CharField(source='approved_by.get_full_name', read_only=True)
    returned_quantity = serializers.IntegerField(read_only=True)

    class Meta:
        model = SaleItem
        fields = (
            'id', 'spare_part', 'spare_part_name', 'quantity',
            'unit_cost', 'unit_price', 'subtotal', 'price_alert', 'approved_by', 'approved_by_name',
            'returned_quantity',
        )


class SaleReturnItemSerializer(serializers.ModelSerializer):
    spare_part_name = serializers.CharField(source='sale_item.spare_part.name', read_only=True)
    subtotal = serializers.DecimalField(max_digits=15, decimal_places=2, read_only=True)

    class Meta:
        model = SaleReturnItem
        fields = ('id', 'sale_item', 'spare_part_name', 'quantity', 'unit_price', 'unit_cost', 'subtotal')


class SaleReturnSerializer(serializers.ModelSerializer):
    items = SaleReturnItemSerializer(many=True, read_only=True)
    processed_by_name = serializers.CharField(source='processed_by.get_full_name', read_only=True)
    total_amount = serializers.DecimalField(max_digits=15, decimal_places=2, read_only=True)

    class Meta:
        model = SaleReturn
        fields = (
            'id', 'sale', 'reason', 'processed_by', 'processed_by_name',
            'created_at', 'items', 'total_amount',
        )
        read_only_fields = ('sale', 'processed_by')


class SaleSerializer(serializers.ModelSerializer):
    items = SaleItemSerializer(many=True, read_only=True)
    returns = SaleReturnSerializer(many=True, read_only=True)
    sold_by_name = serializers.CharField(source='sold_by.get_full_name', read_only=True)
    total_amount = serializers.SerializerMethodField()

    class Meta:
        model = Sale
        fields = (
            'id', 'invoice_number', 'public_token', 'customer_name', 'customer_phone',
            'payment_method', 'sold_by', 'sold_by_name', 'sold_at',
            'created_at', 'items', 'returns', 'total_amount',
        )
        read_only_fields = ('invoice_number', 'public_token', 'sold_by')

    def get_total_amount(self, obj):
        return sum((item.subtotal for item in obj.items.all()), 0)


class PublicSaleItemSerializer(serializers.ModelSerializer):
    spare_part_name = serializers.CharField(source='spare_part.name', read_only=True)
    subtotal = serializers.DecimalField(max_digits=15, decimal_places=2, read_only=True)

    class Meta:
        model = SaleItem
        fields = ('spare_part_name', 'quantity', 'unit_price', 'subtotal')


class PublicSaleSerializer(serializers.ModelSerializer):
    """Customer-facing invoice view: no id, cost, staff, or return details."""

    items = PublicSaleItemSerializer(many=True, read_only=True)
    total_amount = serializers.SerializerMethodField()

    class Meta:
        model = Sale
        fields = ('invoice_number', 'customer_name', 'payment_method', 'sold_at', 'items', 'total_amount')

    def get_total_amount(self, obj):
        return sum((item.subtotal for item in obj.items.all()), 0)


class ManagerApprovalSerializer(serializers.Serializer):
    username = serializers.CharField()
    pin = serializers.CharField()


class SaleCreateSerializer(serializers.Serializer):
    customer_name = serializers.CharField(max_length=200, required=False, allow_blank=True)
    customer_phone = serializers.CharField(max_length=30, required=False, allow_blank=True)
    payment_method = serializers.ChoiceField(choices=Sale.PaymentMethod.choices)
    items = SaleItemInputSerializer(many=True)
    manager_approval = ManagerApprovalSerializer(required=False)

    def validate_items(self, value):
        if not value:
            raise serializers.ValidationError('At least one item is required.')
        return value


class SaleReturnItemInputSerializer(serializers.Serializer):
    sale_item = serializers.PrimaryKeyRelatedField(queryset=SaleItem.objects.all())
    quantity = serializers.IntegerField(min_value=1)


class SaleReturnCreateSerializer(serializers.Serializer):
    reason = serializers.CharField(max_length=255, required=False, allow_blank=True)
    items = SaleReturnItemInputSerializer(many=True)

    def validate_items(self, value):
        if not value:
            raise serializers.ValidationError('At least one item is required.')
        return value
