from django.db import models


class Event(models.Model):
    """An event within a project, can be hierarchical."""
    EVENT_TYPE_CHOICES = [
        ('project', 'Project'),
        ('site', 'Site'),
        ('transect', 'Transect'),
        ('visit', 'Visit'),
        ('sample', 'Sample'),
        ('biotope_mapping_unit', 'Biotope Mapping Unit'),
        ('note', 'Note'),
    ]

    parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name='children')
    name = models.CharField(max_length=255)
    event_type = models.CharField(max_length=50, choices=EVENT_TYPE_CHOICES)
    path = models.CharField(max_length=500, blank=True, db_index=True, help_text='Materialized path like "/1/2/3/"')
    depth = models.IntegerField(default=0, db_index=True, help_text='Depth in hierarchy (0 for root)')
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    location_note = models.CharField(max_length=500, blank=True, null=True)
    footprintWKT = models.TextField(blank=True, null=True, help_text='Geometry in WKT format')
    habitat = models.CharField(max_length=255, blank=True, null=True)
    fieldNotes = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['start_date', 'name']
        indexes = [
            models.Index(fields=['path']),
            models.Index(fields=['depth']),
        ]

    def __str__(self):
        return f"{self.name} ({self.get_event_type_display()})"


    def get_descendants(self):
        """
        Get all descendant events using the materialized path.
        
        Path format: event's own ID is the last element in the path.
        Example: If Project (id=1) has path="/1/", descendants have paths like "/1/2/", "/1/2/3/", etc.
        
        Requires path field to be populated (done via migration).
        """
        # Path format: event's own ID is last element, so self.path is like "/1/" or "/1/2/"
        # Descendants have paths that start with self.path but are longer (more IDs)
        # Example: if self.path="/1/", descendants are "/1/2/", "/1/2/3/", etc.
        return Event.objects.filter(path__startswith=self.path).exclude(pk=self.pk)

    def get_descendant_ids(self):
        """Get IDs of all descendant events."""
        return self.get_descendants().values_list('id', flat=True)
    
    def get_breadcrumb(self):
        """
        Build breadcrumb trail from project to current event.
        
        Returns list of dicts with id, name, and event_type.
        """
        breadcrumb = []
        current = self
        
        # Traverse up to find all ancestors
        ancestors = []
        while current:
            ancestors.insert(0, current)  # Insert at beginning to maintain root-to-leaf order
            current = current.parent
        
        # Create breadcrumb items (all ancestors including current event)
        for ancestor in ancestors:
            breadcrumb.append({
                'id': ancestor.id,
                'name': ancestor.name,
                'event_type': ancestor.event_type,
            })
        
        return breadcrumb


class Occurrence(models.Model):
    """A taxon occurrence recorded at an event."""
    event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='occurrences')
    occurrence_id = models.CharField(max_length=255, blank=True, null=True)
    taxon_name = models.CharField(max_length=255)
    taxon_id = models.CharField(max_length=255, blank=True, null=True)
    common_name = models.CharField(max_length=255, blank=True, null=True)
    grid_reference = models.CharField(max_length=50, blank=True, null=True)
    latitude = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True)
    longitude = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True)
    abundance = models.CharField(max_length=100, blank=True, null=True)
    recorded_by = models.CharField(max_length=255, blank=True, null=True)
    occurrence_date = models.DateField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['occurrence_date', 'taxon_name']

    def __str__(self):
        return f"{self.taxon_name} at {self.event.name}"


class EventAttribute(models.Model):
    """Measurements or facts associated with an event or occurrence."""
    event = models.ForeignKey(Event, on_delete=models.CASCADE, blank=True, null=True, related_name='measurements')
    occurrence = models.ForeignKey(Occurrence, on_delete=models.CASCADE, blank=True, null=True, related_name='measurements')
    attribute_type = models.CharField(max_length=100)
    attribute_value = models.CharField(max_length=500)
    unit = models.CharField(max_length=50, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['attribute_type', 'created_at']

    def __str__(self):
        target = self.occurrence if self.occurrence else self.event
        return f"{self.attribute_type}: {self.attribute_value} ({target})"
