import logging

from django.db import transaction
from django.utils.translation import gettext_lazy
from rest_framework.exceptions import ValidationError
from rest_framework.generics import get_object_or_404

from rest_framework import serializers
from inputs.enums import LogInputType
from inputs.models import LogInput, LogInputArmaIF, LogInputEndpoint
from inputs.services.inputs import create_input, update_input
from inputs.services.update_config import update_arma_config, update_endpoint_config

_log = logging.getLogger(__name__)


class InputSerializer(serializers.ModelSerializer):
    port = serializers.IntegerField(min_value=1500, max_value=65535, write_only=True)

    class Meta:
        model = LogInput
        fields = ['id', 'label', 'type', 'can_delete', 'port']

    def validate_port(self, value):
        input_kwargs = {}
        if self.instance:
            loginput_id = self.instance.pk
            input_kwargs = {'input': loginput_id}
        if LogInputArmaIF.objects.filter(port=value).exclude(**input_kwargs).exists() or \
                LogInputEndpoint.objects.filter(port=value).exclude(**input_kwargs).exists():
            raise ValidationError(gettext_lazy('This port is already in use'))
        return value

    def create(self, validated_data):
        with transaction.atomic():
            port = validated_data.pop('port')
            input_instance = super().create(validated_data)
            create_input(input_instance, port)
            _log.info(
                f'User [{self.context["request"].user}] create logstash config [{input_instance.config_file_name}]')
            return input_instance

    def update(self, instance, validated_data):
        with transaction.atomic():
            port = validated_data.pop('port', None)
            input_instance = super().update(instance, validated_data)
            update_input(input_instance, port)
            _log.info(
                f'User [{self.context["request"].user}] update logstash config [{input_instance.config_file_name}]')
            return input_instance

    def to_representation(self, instance: LogInput):
        log_input_data = super().to_representation(instance)
        if instance.type == LogInputType.ARMAIF:
            log_input_data['port'] = instance.loginputarmaif.port
        elif instance.type == LogInputType.ENDPOINT:
            log_input_data['port'] = instance.loginputendpoint.port
        return log_input_data
