from django.db import models
from django.db.models import Q
from django.utils.text import slugify
import uuid
from status.models import Status
from organization.models import BaseTenantModel, BaseOrganizationModel

from django.core.exceptions import ValidationError

def get_default_status_pk():
    try:
        return Status.objects.get(slug='available-time_slot').pk
    except Status.DoesNotExist:
        return None

class TimeSlot(BaseTenantModel):
    id = models.AutoField(primary_key=True)
    start_time = models.TimeField()
    end_time = models.TimeField()
    slot_name = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100, blank=True)
    status = models.ForeignKey(Status, on_delete=models.CASCADE, default=get_default_status_pk, limit_choices_to={'type': 'time_slot'})
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['end_time']
        constraints = [
            models.UniqueConstraint(
                fields=['organization', 'start_time', 'end_time'],
                name='unique_timeslot_per_org'
            ),
            models.UniqueConstraint(
                fields=['organization', 'slot_name'],
                name='unique_slot_name_per_org'
            )
        ]

    def clean(self):
        super().clean()
        if self.start_time and self.end_time:
            # Basic validation: start before end
            if self.end_time <= self.start_time:
                raise ValidationError({
                    'end_time': 'End time must be greater than start time'
                })

            # Overlap validation for active slots
            if self.is_active:
                # Query for other active slots that overlap in time
                # Overlap logic: (StartA < EndB) and (EndA > StartB)
                overlap_query = Q(
                    is_active=True,
                    start_time__lt=self.end_time,
                    end_time__gt=self.start_time
                )

                # Scope validation:
                # 1. If this slot is global, it only checks against other active global slots.
                # 2. If this slot belongs to an organization, it only checks against other active slots 
                #    within the same organization. There is no cross-validation between global and org slots.
                if self.is_global:
                    overlap_query &= Q(is_global=True)
                else:
                    overlap_query &= Q(organization=self.organization, is_global=False)
                
                # Exclude current instance when updating
                overlaps = TimeSlot.objects.filter(overlap_query)
                if self.pk:
                    overlaps = overlaps.exclude(pk=self.pk)

                if overlaps.exists():
                    other = overlaps.first()
                    org_info = " (Global)" if other.is_global else (f" (Org: {other.organization.code})" if other.organization else "")
                    raise ValidationError(
                        f"Time slot overlaps with an existing active slot: {other.slot_name}{org_info} [{other.start_time} - {other.end_time}]"
                    )

    def save(self, *args, **kwargs):
        self.clean()
        if not self.slug:
            org_code = self.organization.code if self.organization else "global"
            # Format times to HHMM for a cleaner slug, or just use string representation
            start = self.start_time.strftime('%H%M') if self.start_time else ""
            end = self.end_time.strftime('%H%M') if self.end_time else ""
            self.slug = slugify(f"{self.slot_name}-{org_code}-{start}-{end}")
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.slot_name} ({self.start_time}-{self.end_time})"