from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _


# ── ChronographAnalysis ───────────────────────────────────────────────────────

class ChronographAnalysis(models.Model):
    """
    A velocity recording session composed of one or more ShotGroups.
    Can be used anonymously or by an authenticated user.
    """
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='chronograph_analyses',
        verbose_name=_('user'),
    )
    name = models.CharField(_('name'), max_length=150)
    date = models.DateField(_('date'))
    notes = models.TextField(_('notes'), blank=True)
    is_public = models.BooleanField(_('public'), default=False)
    created_at = models.DateTimeField(_('created at'), auto_now_add=True)
    updated_at = models.DateTimeField(_('updated at'), auto_now=True)

    class Meta:
        verbose_name = _('chronograph analysis')
        verbose_name_plural = _('chronograph analyses')
        ordering = ['-date', '-created_at']

    def __str__(self):
        owner = self.user.email if self.user_id else _('anonymous')
        return f"{self.name} ({owner})"

    def clean(self):
        if not self.name or not self.name.strip():
            raise ValidationError({'name': _('Name may not be blank.')})


# ── ShotGroup ─────────────────────────────────────────────────────────────────

class ShotGroup(models.Model):
    """
    A named group of shots. Can be nested under a ChronographAnalysis
    or exist as a standalone group (analysis=None).
    """
    # Optional link to a chronograph session; SET_NULL keeps the group alive
    # when an analysis is deleted.
    analysis = models.ForeignKey(
        ChronographAnalysis,
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='shot_groups',
        verbose_name=_('analysis'),
    )
    # Owner for standalone groups (groups nested under an analysis inherit
    # ownership via analysis.user).
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='shot_groups',
        verbose_name=_('user'),
    )
    label = models.CharField(_('label'), max_length=100)
    distance_m = models.DecimalField(
        _('distance (m)'),
        max_digits=7, decimal_places=1,
        null=True, blank=True,
    )
    order = models.PositiveSmallIntegerField(_('order'), default=0)
    notes = models.TextField(_('notes'), blank=True)
    # Intentional cross-app FKs: tools → gears (string refs avoid circular imports)
    ammo_batch = models.ForeignKey(
        'gears.ReloadedAmmoBatch',
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='shot_groups',
        verbose_name=_('reloaded ammo batch'),
    )
    ammo = models.ForeignKey(
        'gears.Ammo',
        null=True, blank=True,
        on_delete=models.SET_NULL,
        related_name='shot_groups',
        verbose_name=_('factory ammo'),
    )

    class Meta:
        verbose_name = _('shot group')
        verbose_name_plural = _('shot groups')
        ordering = ['order', 'id']

    def __str__(self):
        prefix = self.analysis.name if self.analysis_id else _('Standalone')
        return f"{prefix} / {self.label}"

    def clean(self):
        if self.distance_m is not None and self.distance_m <= 0:
            raise ValidationError(
                {'distance_m': _('Distance must be a positive value.')}
            )


# ── Shot ──────────────────────────────────────────────────────────────────────

class Shot(models.Model):
    """A single bullet velocity reading within a ShotGroup."""
    group = models.ForeignKey(
        ShotGroup,
        on_delete=models.CASCADE,
        related_name='shots',
        verbose_name=_('group'),
    )
    shot_number = models.PositiveSmallIntegerField(
        _('shot number'),
        editable=False,
    )
    velocity_fps = models.DecimalField(
        _('velocity (fps)'),
        max_digits=6, decimal_places=1,
    )
    notes = models.CharField(_('notes'), max_length=255, blank=True)

    class Meta:
        verbose_name = _('shot')
        verbose_name_plural = _('shots')
        ordering = ['shot_number']
        constraints = [
            models.UniqueConstraint(
                fields=['group', 'shot_number'],
                name='unique_shot_number_per_group',
            )
        ]

    def __str__(self):
        return f"Shot #{self.shot_number} — {self.velocity_fps} fps"

    def clean(self):
        if self.velocity_fps is not None and self.velocity_fps <= 0:
            raise ValidationError(
                {'velocity_fps': _('Velocity must be a positive value.')}
            )

    def save(self, *args, **kwargs):
        if not self.pk:
            last = (
                Shot.objects
                .filter(group=self.group)
                .order_by('-shot_number')
                .values_list('shot_number', flat=True)
                .first()
            )
            self.shot_number = (last or 0) + 1
        super().save(*args, **kwargs)
