from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from .models import DeutschePostOrder, DeutschePostBulkOrder


class DeutschePostOrderSerializer(serializers.ModelSerializer):
    state_display = serializers.CharField(source='get_state_display', read_only=True)
    label_size_display = serializers.CharField(source='get_label_size_display', read_only=True)
    tracking_url = serializers.SerializerMethodField(read_only=True)
    estimated_delivery_days = serializers.SerializerMethodField(read_only=True)
    shipping_cost_estimate = serializers.SerializerMethodField(read_only=True)
    can_be_finalized = serializers.SerializerMethodField(read_only=True)
    can_be_cancelled = serializers.SerializerMethodField(read_only=True)
    is_trackable = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = DeutschePostOrder
        fields = [
            'id', 'created_at', 'state', 'state_display',
            'order_id', 'customer_ekp', 
            'recipient_name', 'recipient_phone', 'recipient_email',
            'address_line1', 'address_line2', 'address_line3',
            'city', 'address_state', 'postal_code', 'destination_country',
            'product_type', 'service_level', 'shipment_gross_weight',
            'shipment_amount', 'shipment_currency',
            'sender_tax_id', 'importer_tax_id', 'return_item_wanted',
            'cust_ref', 'awb_number', 'barcode', 'tracking_url',
            'label_pdf', 'label_size', 'label_size_display',
            'metadata', 'last_error',
            'estimated_delivery_days', 'shipping_cost_estimate',
            'can_be_finalized', 'can_be_cancelled', 'is_trackable'
        ]
        read_only_fields = [
            'id', 'created_at', 'order_id', 'awb_number', 'barcode',
            'tracking_url', 'metadata', 'last_error', 'label_pdf'
        ]
    
    def get_tracking_url(self, obj):
        return obj.get_tracking_url()
    
    def get_estimated_delivery_days(self, obj):
        return obj.get_estimated_delivery_days()
    
    def get_shipping_cost_estimate(self, obj):
        return float(obj.get_shipping_cost_estimate())
    
    def get_can_be_finalized(self, obj):
        return obj.can_be_finalized()
    
    def get_can_be_cancelled(self, obj):
        return obj.can_be_cancelled()
    
    def get_is_trackable(self, obj):
        return obj.is_trackable()
    
    def validate_destination_country(self, value):
        """Validate country code format."""
        if len(value) != 2:
            raise ValidationError("Country code must be 2 characters (ISO format)")
        return value.upper()
    
    def validate_shipment_gross_weight(self, value):
        """Validate weight is reasonable."""
        if value <= 0:
            raise ValidationError("Shipment weight must be greater than 0")
        if value > 30000:  # 30kg limit for most Deutsche Post products
            raise ValidationError("Shipment weight cannot exceed 30kg (30000g)")
        return value
    
    def validate(self, attrs):
        """Validate the complete order data."""
        # Check required fields for shipping
        required_fields = ['recipient_name', 'address_line1', 'city', 'postal_code', 'destination_country']
        missing_fields = [field for field in required_fields if not attrs.get(field)]
        
        if missing_fields:
            raise ValidationError(f"Required fields missing: {', '.join(missing_fields)}")
        
        # Check contact information
        if not attrs.get('recipient_email') and not attrs.get('recipient_phone'):
            raise ValidationError("Either recipient email or phone is required for delivery notifications")
        
        return attrs


class DeutschePostBulkOrderSerializer(serializers.ModelSerializer):
    deutschepost_order_ids = serializers.ListField(
        child=serializers.IntegerField(),
        write_only=True,
        required=True,
        help_text="List of DeutschePostOrder IDs to include in bulk order"
    )
    status_display = serializers.CharField(source='get_status_display', read_only=True)
    orders_count = serializers.SerializerMethodField(read_only=True)
    total_weight_kg = serializers.SerializerMethodField(read_only=True)
    tracking_url = serializers.SerializerMethodField(read_only=True)
    status_url = serializers.SerializerMethodField(read_only=True)
    can_be_cancelled = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = DeutschePostBulkOrder
        fields = [
            'id', 'created_at', 'status', 'status_display', 
            'bulk_order_id', 'bulk_order_type', 'description',
            'deutschepost_orders', 'deutschepost_order_ids', 'orders_count',
            'total_weight_kg', 'tracking_url', 'status_url', 'can_be_cancelled',
            'bulk_label_pdf', 'paperwork_pdf',
            'metadata', 'last_error'
        ]
        read_only_fields = [
            'id', 'created_at', 'bulk_order_id', 'deutschepost_orders',
            'bulk_label_pdf', 'paperwork_pdf', 'metadata', 'last_error'
        ]
    
    def get_orders_count(self, obj):
        return obj.deutschepost_orders.count()
    
    def get_total_weight_kg(self, obj):
        return obj.get_total_weight_kg()
    
    def get_tracking_url(self, obj):
        return obj.get_tracking_url()
    
    def get_status_url(self, obj):
        return obj.get_bulk_status_url()
    
    def get_can_be_cancelled(self, obj):
        return obj.can_be_cancelled()
    
    def validate_deutschepost_order_ids(self, value):
        """Validate that all orders exist and are eligible for bulk processing."""
        if not value:
            raise ValidationError("At least one Deutsche Post order is required")
            
        errors = []
        orders = DeutschePostOrder.objects.filter(id__in=value)
        
        if len(orders) != len(value):
            missing_ids = set(value) - set(orders.values_list('id', flat=True))
            errors.append(f"Orders not found: {missing_ids}")
        
        for order in orders:
            # Check if order is created remotely
            if not order.order_id:
                errors.append(f"Order {order.id} not created remotely")
                
            # Check if commerce order uses Deutsche Post
            if order.commerce_order:
                if not order.commerce_order.carrier:
                    errors.append(f"Commerce order {order.commerce_order.id} has no carrier")
                elif order.commerce_order.carrier.shipping_method != "deutschepost":
                    errors.append(f"Commerce order {order.commerce_order.id} doesn't use Deutsche Post")
                elif order.commerce_order.status != order.commerce_order.OrderStatus.COMPLETED:
                    errors.append(f"Commerce order {order.commerce_order.id} is not completed")
            
            # Check if order is already in another bulk order
            if order.bulk_orders.exists():
                errors.append(f"Order {order.id} already in bulk order")
        
        if errors:
            raise ValidationError(errors)
            
        return value
    
    def create(self, validated_data):
        order_ids = validated_data.pop('deutschepost_order_ids')
        
        bulk_order = super().create(validated_data)
        
        # Add orders to bulk order
        orders = DeutschePostOrder.objects.filter(id__in=order_ids)
        bulk_order.deutschepost_orders.set(orders)
        
        return bulk_order


class DeutschePostTrackingSerializer(serializers.Serializer):
    """Serializer for tracking information response."""
    order_id = serializers.CharField(read_only=True)
    awb_number = serializers.CharField(read_only=True) 
    barcode = serializers.CharField(read_only=True)
    tracking_url = serializers.URLField(read_only=True)
    state = serializers.CharField(read_only=True)
    last_updated = serializers.DateTimeField(read_only=True)
    tracking_events = serializers.JSONField(read_only=True)