from rest_framework import serializers

from .models import TruckMovement


class TruckMovementSerializer(serializers.ModelSerializer):
    created_by = serializers.CharField(source='created_by.username', read_only=True)
    exited_by = serializers.CharField(source='exited_by.username', read_only=True, default=None)
    current_penalty = serializers.IntegerField(read_only=True)

    class Meta:
        model = TruckMovement
        fields = [
            'id', 'registration_number', 'truck_number', 't_number', 't_date',
            'cargo_description', 'cargo_quantity', 'cargo_unit', 'missing_quantity',
            'entry_datetime', 'exit_datetime', 'photo', 'status',
            'penalty_amount', 'current_penalty', 'created_by', 'exited_by',
        ]
        read_only_fields = [
            'id', 'registration_number', 'entry_datetime', 'exit_datetime',
            'status', 'penalty_amount', 'current_penalty', 'created_by', 'exited_by',
        ]


class TruckEntrySerializer(serializers.ModelSerializer):
    """Creates a new truck entry. The agent types the entry date/time by hand;
    registration_number/created_by are still set server-side."""

    class Meta:
        model = TruckMovement
        fields = [
            'id', 'registration_number', 'truck_number', 't_number', 't_date',
            'cargo_description', 'cargo_quantity', 'cargo_unit', 'missing_quantity',
            'photo', 'entry_datetime', 'status'
        ]
        read_only_fields = ['id', 'registration_number', 'status']
        extra_kwargs = {'entry_datetime': {'required': True}}

    def create(self, validated_data):
        validated_data['created_by'] = self.context['request'].user
        return super().create(validated_data)


class TruckUpdateSerializer(serializers.ModelSerializer):
    """Edits an existing movement. Changing entry/exit times recomputes the
    penalty so the recorded amount always matches the recorded times."""

    class Meta:
        model = TruckMovement
        fields = [
            'id', 'registration_number', 'truck_number', 't_number', 't_date',
            'cargo_description', 'cargo_quantity', 'cargo_unit', 'missing_quantity',
            'photo', 'entry_datetime', 'exit_datetime', 'status', 'penalty_amount',
        ]
        read_only_fields = ['id', 'registration_number', 'penalty_amount']

    def validate(self, attrs):
        entry = attrs.get('entry_datetime', getattr(self.instance, 'entry_datetime', None))
        exit_dt = attrs.get('exit_datetime', getattr(self.instance, 'exit_datetime', None))
        if entry and exit_dt and exit_dt < entry:
            raise serializers.ValidationError(
                {'exit_datetime': "La date de sortie ne peut pas précéder la date d'entrée."}
            )
        status = attrs.get('status', getattr(self.instance, 'status', None))
        if status == TruckMovement.Status.EXITED and not exit_dt:
            raise serializers.ValidationError(
                {'exit_datetime': 'Une date de sortie est requise pour un camion sorti.'}
            )
        return attrs

    def update(self, instance, validated_data):
        movement = super().update(instance, validated_data)
        if movement.exit_datetime and movement.status == TruckMovement.Status.EXITED:
            movement.penalty_amount = movement.calculate_penalty(at=movement.exit_datetime)
        else:
            movement.exit_datetime = None
            movement.exited_by = None
            movement.status = TruckMovement.Status.IN_PARK
            movement.penalty_amount = 0
        movement.save()
        return movement


class TruckExitSerializer(serializers.Serializer):
    """Looks up a truck by registration_number and records its exit."""
    registration_number = serializers.CharField()

    def validate_registration_number(self, value):
        try:
            movement = TruckMovement.objects.get(registration_number=value)
        except TruckMovement.DoesNotExist:
            raise serializers.ValidationError('No truck movement found with this registration number.')
        if movement.status == TruckMovement.Status.EXITED:
            raise serializers.ValidationError('This truck has already exited.')
        self._movement = movement
        return value

    def save(self, **kwargs):
        user = self.context['request'].user
        self._movement.register_exit(exited_by=user)
        return self._movement
