from rest_framework import serializers
from .models import Transfer, TransferItem, TransferComment, TransferEvent
from apps.business.models import Location
from apps.inventory.models import InventoryItem


class TransferItemSerializer(serializers.ModelSerializer):
    """Serializer for transfer items"""
    
    inventory_item = serializers.SerializerMethodField()
    variance = serializers.ReadOnlyField()
    has_discrepancy = serializers.ReadOnlyField()
    
    class Meta:
        model = TransferItem
        fields = [
            'id', 'inventory_item', 'quantity', 'received_quantity',
            'condition', 'status', 'notes', 'received_notes',
            'variance', 'has_discrepancy', 'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'created_at', 'updated_at']
    
    def get_inventory_item(self, obj):
        return {
            'id': str(obj.inventory_item.id),
            'asset_id': obj.inventory_item.asset_id,
            'brand': {'name': obj.inventory_item.brand.name} if obj.inventory_item.brand else None,
            'model': obj.inventory_item.model,
            'serial_number': obj.inventory_item.serial_number,
        }


class TransferCommentSerializer(serializers.ModelSerializer):
    """Serializer for transfer comments"""
    
    user = serializers.SerializerMethodField()
    
    class Meta:
        model = TransferComment
        fields = [
            'id', 'user', 'text', 'is_internal',
            'created_at', 'updated_at'
        ]
        read_only_fields = ['id', 'user', 'created_at', 'updated_at']
    
    def get_user(self, obj):
        return {
            'id': str(obj.user.id),
            'name': obj.user.get_full_name() or obj.user.username,
            'email': obj.user.email,
        }


class TransferEventSerializer(serializers.ModelSerializer):
    """Serializer for transfer events"""
    
    user = serializers.SerializerMethodField()
    
    class Meta:
        model = TransferEvent
        fields = [
            'id', 'event_type', 'user', 'notes',
            'metadata', 'created_at'
        ]
        read_only_fields = ['id', 'created_at']
    
    def get_user(self, obj):
        if not obj.user:
            return None
        return {
            'id': str(obj.user.id),
            'name': obj.user.get_full_name() or obj.user.username,
        }


class TransferListSerializer(serializers.ModelSerializer):
    """Serializer for transfer list view"""
    
    business = serializers.SerializerMethodField()
    source_location = serializers.SerializerMethodField()
    destination_location = serializers.SerializerMethodField()
    requested_by = serializers.SerializerMethodField()
    total_items_count = serializers.ReadOnlyField()
    total_value = serializers.ReadOnlyField()
    is_overdue = serializers.ReadOnlyField()
    
    class Meta:
        model = Transfer
        fields = [
            'id', 'transfer_number', 'business', 'source_location',
            'destination_location', 'status', 'priority', 'requested_by',
            'requested_date', 'expected_delivery_date', 'total_items_count',
            'total_value', 'is_overdue', 'created_at'
        ]
    
    def get_business(self, obj):
        return {
            'id': str(obj.business.id),
            'name': obj.business.name,
        }
    
    def get_source_location(self, obj):
        return {
            'id': str(obj.source_location.id),
            'name': obj.source_location.name,
            'code': obj.source_location.code,
        }
    
    def get_destination_location(self, obj):
        return {
            'id': str(obj.destination_location.id),
            'name': obj.destination_location.name,
            'code': obj.destination_location.code,
        }
    
    def get_requested_by(self, obj):
        return {
            'id': str(obj.requested_by.id),
            'name': obj.requested_by.get_full_name() or obj.requested_by.username,
            'email': obj.requested_by.email,
        }


class TransferDetailSerializer(serializers.ModelSerializer):
    """Serializer for transfer detail view"""
    
    business = serializers.SerializerMethodField()
    source_location = serializers.SerializerMethodField()
    destination_location = serializers.SerializerMethodField()
    requested_by = serializers.SerializerMethodField()
    approved_by = serializers.SerializerMethodField()
    received_by = serializers.SerializerMethodField()
    items = TransferItemSerializer(many=True, read_only=True)
    comments = TransferCommentSerializer(many=True, read_only=True)
    events = TransferEventSerializer(many=True, read_only=True)
    total_items_count = serializers.ReadOnlyField()
    total_value = serializers.ReadOnlyField()
    duration_days = serializers.ReadOnlyField()
    is_overdue = serializers.ReadOnlyField()
    
    class Meta:
        model = Transfer
        fields = [
            'id', 'transfer_number', 'business', 'source_location',
            'destination_location', 'status', 'priority', 'requested_by',
            'approved_by', 'received_by', 'requested_date', 'approved_date',
            'shipped_date', 'expected_delivery_date', 'delivered_date',
            'received_date', 'carrier_name', 'tracking_number', 'shipping_method',
            'estimated_cost', 'actual_cost', 'has_discrepancies',
            'discrepancy_report', 'notes', 'items', 'comments', 'events',
            'total_items_count', 'total_value', 'duration_days', 'is_overdue',
            'created_at', 'updated_at'
        ]
    
    def get_business(self, obj):
        return {
            'id': str(obj.business.id),
            'name': obj.business.name,
        }
    
    def get_source_location(self, obj):
        return {
            'id': str(obj.source_location.id),
            'name': obj.source_location.name,
            'code': obj.source_location.code,
        }
    
    def get_destination_location(self, obj):
        return {
            'id': str(obj.destination_location.id),
            'name': obj.destination_location.name,
            'code': obj.destination_location.code,
        }
    
    def get_requested_by(self, obj):
        return {
            'id': str(obj.requested_by.id),
            'name': obj.requested_by.get_full_name() or obj.requested_by.username,
            'email': obj.requested_by.email,
        }
    
    def get_approved_by(self, obj):
        if not obj.approved_by:
            return None
        return {
            'id': str(obj.approved_by.id),
            'name': obj.approved_by.get_full_name() or obj.approved_by.username,
            'email': obj.approved_by.email,
        }
    
    def get_received_by(self, obj):
        if not obj.received_by:
            return None
        return {
            'id': str(obj.received_by.id),
            'name': obj.received_by.get_full_name() or obj.received_by.username,
            'email': obj.received_by.email,
        }


class CreateTransferSerializer(serializers.Serializer):
    """Serializer for creating transfers"""
    
    business_id = serializers.UUIDField()
    source_location_id = serializers.UUIDField()
    destination_location_id = serializers.UUIDField()
    items = serializers.ListField(
        child=serializers.DictField(),
        min_length=1
    )
    priority = serializers.ChoiceField(
        choices=['LOW', 'MEDIUM', 'HIGH', 'URGENT'],
        default='MEDIUM'
    )
    expected_delivery_date = serializers.DateField(required=False, allow_null=True)
    notes = serializers.CharField(required=False, allow_blank=True)
    
    def validate(self, data):
        # Validate locations belong to same business
        try:
            source = Location.objects.get(id=data['source_location_id'])
            destination = Location.objects.get(id=data['destination_location_id'])
        except Location.DoesNotExist:
            raise serializers.ValidationError("Invalid location ID")
        
        if str(source.business_id) != str(data['business_id']):
            raise serializers.ValidationError("Source location does not belong to business")
        
        if str(destination.business_id) != str(data['business_id']):
            raise serializers.ValidationError("Destination location does not belong to business")
        
        if source.id == destination.id:
            raise serializers.ValidationError("Source and destination must be different")
        
        # Validate items
        for item_data in data['items']:
            if 'inventory_item_id' not in item_data:
                raise serializers.ValidationError("Each item must have inventory_item_id")
            
            if 'quantity' not in item_data or item_data['quantity'] < 1:
                raise serializers.ValidationError("Each item must have quantity >= 1")
            
            try:
                inventory_item = InventoryItem.objects.get(id=item_data['inventory_item_id'])
            except InventoryItem.DoesNotExist:
                raise serializers.ValidationError(f"Invalid inventory item ID: {item_data['inventory_item_id']}")
            
            if str(inventory_item.location_id) != str(source.id):
                raise serializers.ValidationError(
                    f"Item {inventory_item.asset_id} is not at source location"
                )
            
            if inventory_item.status != 'IN_STOCK':
                raise serializers.ValidationError(
                    f"Item {inventory_item.asset_id} is not available (status: {inventory_item.status})"
                )
        
        return data
    
    def create(self, validated_data):
        items_data = validated_data.pop('items')
        user = self.context['request'].user
        
        # Create transfer
        transfer = Transfer.objects.create(
            business_id=validated_data['business_id'],
            source_location_id=validated_data['source_location_id'],
            destination_location_id=validated_data['destination_location_id'],
            priority=validated_data.get('priority', 'MEDIUM'),
            expected_delivery_date=validated_data.get('expected_delivery_date'),
            notes=validated_data.get('notes', ''),
            requested_by=user,
            status='PENDING'
        )
        
        # Create transfer items
        for item_data in items_data:
            TransferItem.objects.create(
                transfer=transfer,
                inventory_item_id=item_data['inventory_item_id'],
                quantity=item_data['quantity'],
                notes=item_data.get('notes', '')
            )
        
        # Create creation event
        TransferEvent.objects.create(
            transfer=transfer,
            event_type='CREATED',
            user=user,
            notes=f"Transfer created by {user.get_full_name() or user.username}"
        )
        
        return transfer


class UpdateTransferSerializer(serializers.Serializer):
    """Serializer for updating transfers"""
    
    notes = serializers.CharField(required=False, allow_blank=True)
    priority = serializers.ChoiceField(
        choices=['LOW', 'MEDIUM', 'HIGH', 'URGENT'],
        required=False
    )
    expected_delivery_date = serializers.DateField(required=False, allow_null=True)


class ApproveTransferSerializer(serializers.Serializer):
    """Serializer for approving transfers"""
    
    notes = serializers.CharField(required=False, allow_blank=True)


class RejectTransferSerializer(serializers.Serializer):
    """Serializer for rejecting transfers"""
    
    reason = serializers.CharField(required=True)


class ShipTransferSerializer(serializers.Serializer):
    """Serializer for shipping transfers"""
    
    carrier_name = serializers.CharField(required=False, allow_blank=True)
    tracking_number = serializers.CharField(required=False, allow_blank=True)
    shipping_method = serializers.CharField(required=False, allow_blank=True)
    estimated_cost = serializers.DecimalField(
        max_digits=10,
        decimal_places=2,
        required=False,
        allow_null=True
    )


class ReceiveTransferSerializer(serializers.Serializer):
    """Serializer for receiving transfers"""
    
    items = serializers.ListField(
        child=serializers.DictField(),
        min_length=1
    )
    has_discrepancies = serializers.BooleanField(default=False)
    discrepancy_report = serializers.CharField(required=False, allow_blank=True)
    
    def validate_items(self, value):
        """Validate items data"""
        for item_data in value:
            if 'item_id' not in item_data:
                raise serializers.ValidationError("Each item must have item_id")
            
            if 'received_quantity' not in item_data:
                raise serializers.ValidationError("Each item must have received_quantity")
            
            if 'condition' not in item_data:
                raise serializers.ValidationError("Each item must have condition")
            
            if item_data['condition'] not in ['Good', 'Damaged', 'Missing']:
                raise serializers.ValidationError("Invalid condition value")
            
            if item_data['received_quantity'] < 0:
                raise serializers.ValidationError("Received quantity cannot be negative")
        
        return value


class AddCommentSerializer(serializers.Serializer):
    """Serializer for adding comments"""
    
    text = serializers.CharField(required=True)
    is_internal = serializers.BooleanField(default=False)


class CancelTransferSerializer(serializers.Serializer):
    """Serializer for cancelling transfers"""
    
    reason = serializers.CharField(required=True)