"""
Модели параметров сигнала (Parameter, SigmaParameter).
"""
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import ExpressionWrapper, F

from .defaults import (
    get_default_polarization,
    get_default_modulation,
    get_default_standard,
)


class Parameter(models.Model):
    id_satellite = models.ForeignKey(
        'mainapp.Satellite',
        on_delete=models.PROTECT,
        related_name="parameters",
        verbose_name="Спутник",
        null=True,
    )
    polarization = models.ForeignKey(
        'mainapp.Polarization',
        default=get_default_polarization,
        on_delete=models.SET_DEFAULT,
        related_name="polarizations",
        null=True,
        blank=True,
        verbose_name="Поляризация",
    )
    frequency = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="Частота, МГц",
        db_index=True,
        help_text="Центральная частота сигнала",
    )
    freq_range = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="Полоса частот, МГц",
        help_text="Полоса частот сигнала",
    )
    bod_velocity = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="Символьная скорость, БОД",
        help_text="Символьная скорость должна быть положительной",
    )
    modulation = models.ForeignKey(
        'mainapp.Modulation',
        default=get_default_modulation,
        on_delete=models.SET_DEFAULT,
        related_name="modulations",
        null=True,
        blank=True,
        verbose_name="Модуляция",
    )
    snr = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="ОСШ",
        help_text="Отношение сигнал/шум",
    )
    standard = models.ForeignKey(
        'mainapp.Standard',
        default=get_default_standard,
        on_delete=models.SET_DEFAULT,
        related_name="standards",
        null=True,
        blank=True,
        verbose_name="Стандарт",
    )
    objitem = models.OneToOneField(
        'mainapp.ObjItem',
        on_delete=models.CASCADE,
        related_name="parameter_obj",
        verbose_name="Объект",
        null=True,
        blank=True,
        help_text="Связанный объект",
    )

    def clean(self):
        """Валидация на уровне модели"""
        super().clean()

        # Проверка что частота больше полосы частот
        if self.frequency and self.freq_range:
            if self.freq_range > self.frequency:
                raise ValidationError(
                    {"freq_range": "Полоса частот не может быть больше частоты"}
                )

        # Проверка что символьная скорость соответствует полосе частот
        if self.bod_velocity and self.freq_range:
            if self.bod_velocity > self.freq_range * 1000000:  # Конвертация МГц в Гц
                raise ValidationError(
                    {
                        "bod_velocity": "Символьная скорость не может превышать полосу частот"
                    }
                )

    def __str__(self):
        polarization_name = self.polarization.name if self.polarization else "-"
        modulation_name = self.modulation.name if self.modulation else "-"
        return f"Источник-{self.frequency}:{self.freq_range} МГц:{polarization_name}:{modulation_name}"

    class Meta:
        verbose_name = "ВЧ загрузка"
        verbose_name_plural = "ВЧ загрузки"
        indexes = [
            models.Index(fields=["id_satellite", "frequency"]),
            models.Index(fields=["frequency", "polarization"]),
        ]


class SigmaParameter(models.Model):
    TRANSFERS = [(-1.0, "-"), (9750.0, "9750 МГц"), (10750.0, "10750 МГц")]

    id_satellite = models.ForeignKey(
        'mainapp.Satellite',
        on_delete=models.PROTECT,
        related_name="sigmapar_sat",
        verbose_name="Спутник",
    )
    transfer = models.FloatField(
        choices=TRANSFERS,
        default=-1.0,
        verbose_name="Перенос по частоте",
        help_text="Выберите перенос по частоте",
    )
    status = models.CharField(
        max_length=20,
        blank=True,
        null=True,
        verbose_name="Статус",
        help_text="Статус измерения",
    )
    frequency = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="Частота, МГц",
        db_index=True,
        help_text="Центральная частота сигнала",
    )
    transfer_frequency = models.GeneratedField(
        expression=ExpressionWrapper(
            F("frequency") + F("transfer"), output_field=models.FloatField()
        ),
        output_field=models.FloatField(),
        db_persist=True,
        null=True,
        blank=True,
        verbose_name="Частота в Ku, МГц",
    )
    freq_range = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="Полоса частот, МГц",
        help_text="Полоса частот",
    )
    power = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="Мощность, дБм",
        help_text="Мощность сигнала",
    )
    bod_velocity = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="Символьная скорость, БОД",
        help_text="Символьная скорость должна быть положительной",
    )
    polarization = models.ForeignKey(
        'mainapp.Polarization',
        default=get_default_polarization,
        on_delete=models.SET_DEFAULT,
        related_name="polarizations_sigma",
        null=True,
        blank=True,
        verbose_name="Поляризация",
    )
    modulation = models.ForeignKey(
        'mainapp.Modulation',
        default=get_default_modulation,
        on_delete=models.SET_DEFAULT,
        related_name="modulations_sigma",
        null=True,
        blank=True,
        verbose_name="Модуляция",
    )
    snr = models.FloatField(
        default=0,
        null=True,
        blank=True,
        verbose_name="ОСШ, Дб",
        validators=[MinValueValidator(-50), MaxValueValidator(100)],
        help_text="Отношение сигнал/шум в диапазоне от -50 до 100 дБ",
    )
    standard = models.ForeignKey(
        'mainapp.Standard',
        default=get_default_standard,
        on_delete=models.SET_DEFAULT,
        related_name="standards_sigma",
        null=True,
        blank=True,
        verbose_name="Стандарт",
    )
    packets = models.BooleanField(
        null=True,
        blank=True,
        verbose_name="Пакетность",
        help_text="Наличие пакетной передачи",
    )
    datetime_begin = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="Время начала измерения",
        help_text="Дата и время начала измерения",
    )
    datetime_end = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="Время окончания измерения",
        help_text="Дата и время окончания измерения",
    )
    parameter = models.ForeignKey(
        'mainapp.Parameter',
        on_delete=models.SET_NULL,
        related_name="sigma_parameter",
        verbose_name="ВЧ",
        null=True,
        blank=True,
    )

    def clean(self):
        """Валидация на уровне модели"""
        super().clean()

        # Проверка что время окончания больше времени начала
        if self.datetime_begin and self.datetime_end:
            if self.datetime_end < self.datetime_begin:
                raise ValidationError(
                    {"datetime_end": "Время окончания должно быть позже времени начала"}
                )

        # Проверка что частота больше полосы частот
        if self.frequency and self.freq_range:
            if self.freq_range > self.frequency:
                raise ValidationError(
                    {"freq_range": "Полоса частот не может быть больше частоты"}
                )

    def __str__(self):
        modulation_name = self.modulation.name if self.modulation else "-"
        return f"Sigma-{self.frequency}:{self.freq_range} МГц:{modulation_name}"

    class Meta:
        verbose_name = "ВЧ sigma"
        verbose_name_plural = "ВЧ sigma"
