# """
# Channel Schedule Management Models

# This module contains models for managing channel broadcasting schedules:
# - ChannelSchedule: Scheduled programming and events for channels

# These models handle the scheduling of content, maintenance windows,
# special events, and test broadcasts for television channels.
# """

# from django.db import models
# from django.utils import timezone
# from django.utils.translation import gettext_lazy as _
# from django.core.exceptions import ValidationError

# from apps.common.models import BaseModel
# from apps.channels.models import Channel


# class ChannelSchedule(BaseModel):
#     """
#     Channel broadcasting schedule management.
    
#     Manages scheduled programming, maintenance windows, special events,
#     and test broadcasts for television channels. Supports different
#     types of scheduled content and ad insertion settings.
    
#     Attributes:
#         channel: Foreign key to the channel this schedule belongs to
#         title: Name/title of the scheduled content or event
#         schedule_type: Type of scheduled content (regular, special, maintenance, test)
#         start_time: When the scheduled content begins
#         end_time: When the scheduled content ends
#         description: Detailed description of the scheduled content
#         content_url: Primary URL for the scheduled content
#         backup_content_url: Fallback URL if primary content fails
#         allow_ads: Whether ads are allowed during this scheduled time
#         ad_break_duration: Duration of ad breaks in seconds
#         is_active: Whether this schedule entry is currently active
        
#     Related Models:
#         - Channel: Many-to-one relationship (channel can have multiple schedules)
#     """
    
#     SCHEDULE_TYPES = [
#         ("regular", _("Regular Programming")),
#         ("special", _("Special Event")),
#         ("maintenance", _("Maintenance Window")),
#         ("test", _("Test Broadcast")),
#         ("emergency", _("Emergency Broadcast")),
#         ("replay", _("Replay/Rerun")),
#     ]
    
#     # Relationships
#     channel = models.ForeignKey(
#         Channel,
#         on_delete=models.CASCADE,
#         related_name="schedules",
#         verbose_name=_("Channel"),
#         help_text=_("Channel this schedule entry belongs to")
#     )
    
#     # Basic Information
#     title = models.CharField(
#         max_length=255,
#         verbose_name=_("Schedule Title"),
#         help_text=_("Name or title of the scheduled content or event")
#     )
#     schedule_type = models.CharField(
#         max_length=20,
#         choices=SCHEDULE_TYPES,
#         default="regular",
#         verbose_name=_("Schedule Type"),
#         help_text=_("Type of scheduled content or event")
#     )
    
#     # Timing
#     start_time = models.DateTimeField(
#         verbose_name=_("Start Time"),
#         help_text=_("When the scheduled content begins")
#     )
#     end_time = models.DateTimeField(
#         verbose_name=_("End Time"),
#         help_text=_("When the scheduled content ends")
#     )
    
#     # Content Details
#     description = models.TextField(
#         blank=True,
#         verbose_name=_("Description"),
#         help_text=_("Detailed description of the scheduled content")
#     )
#     content_url = models.URLField(
#         blank=True,
#         verbose_name=_("Content URL"),
#         help_text=_("Primary URL for the scheduled content stream")
#     )
#     backup_content_url = models.URLField(
#         blank=True,
#         verbose_name=_("Backup Content URL"),
#         help_text=_("Fallback URL if primary content stream fails")
#     )
    
#     # Content Metadata
#     content_rating = models.CharField(
#         max_length=10,
#         blank=True,
#         verbose_name=_("Content Rating"),
#         help_text=_("Content rating (G, PG, PG-13, R, etc.)")
#     )
#     language = models.CharField(
#         max_length=50,
#         blank=True,
#         verbose_name=_("Language"),
#         help_text=_("Primary language of the scheduled content")
#     )
    
#     # Ad Settings
#     allow_ads = models.BooleanField(
#         default=True,
#         verbose_name=_("Allow Advertisements"),
#         help_text=_("Whether ads are allowed during this scheduled time")
#     )
#     ad_break_duration = models.PositiveIntegerField(
#         default=120,
#         verbose_name=_("Ad Break Duration"),
#         help_text=_("Duration of ad breaks in seconds")
#     )
#     max_ad_breaks_per_hour = models.PositiveIntegerField(
#         default=4,
#         verbose_name=_("Max Ad Breaks Per Hour"),
#         help_text=_("Maximum number of ad breaks allowed per hour")
#     )
    
#     # Priority and Overrides
#     priority = models.PositiveIntegerField(
#         default=1,
#         verbose_name=_("Priority"),
#         help_text=_("Priority level for schedule conflicts (higher = more important)")
#     )
#     can_be_preempted = models.BooleanField(
#         default=True,
#         verbose_name=_("Can Be Preempted"),
#         help_text=_("Whether this schedule can be overridden by higher priority content")
#     )
    
#     # Status and Control
#     is_active = models.BooleanField(
#         default=True,
#         verbose_name=_("Is Active"),
#         help_text=_("Whether this schedule entry is currently active")
#     )
#     auto_start = models.BooleanField(
#         default=True,
#         verbose_name=_("Auto Start"),
#         help_text=_("Whether content should start automatically at the scheduled time")
#     )
#     auto_end = models.BooleanField(
#         default=True,
#         verbose_name=_("Auto End"),
#         help_text=_("Whether content should end automatically at the scheduled time")
#     )
    
#     # Notifications and Alerts
#     send_start_notification = models.BooleanField(
#         default=False,
#         verbose_name=_("Send Start Notification"),
#         help_text=_("Send notification when content starts")
#     )
#     send_end_notification = models.BooleanField(
#         default=False,
#         verbose_name=_("Send End Notification"),
#         help_text=_("Send notification when content ends")
#     )
#     notification_recipients = models.JSONField(
#         default=list,
#         blank=True,
#         verbose_name=_("Notification Recipients"),
#         help_text=_("List of email addresses or user IDs to notify")
#     )
    
#     # Tracking and Metadata
#     actual_start_time = models.DateTimeField(
#         null=True,
#         blank=True,
#         verbose_name=_("Actual Start Time"),
#         help_text=_("When the content actually started (for tracking)")
#     )
#     actual_end_time = models.DateTimeField(
#         null=True,
#         blank=True,
#         verbose_name=_("Actual End Time"),
#         help_text=_("When the content actually ended (for tracking)")
#     )
    
#     # Additional metadata
#     metadata = models.JSONField(
#         default=dict,
#         blank=True,
#         verbose_name=_("Metadata"),
#         help_text=_("Additional metadata for the scheduled content")
#     )
    
#     class Meta:
#         db_table = "channel_schedules"
#         ordering = ["channel", "start_time"]
#         verbose_name = _("Channel Schedule")
#         verbose_name_plural = _("Channel Schedules")
#         indexes = [
#             models.Index(fields=["channel", "start_time"]),
#             models.Index(fields=["start_time", "end_time"]),
#             models.Index(fields=["schedule_type", "is_active"]),
#             models.Index(fields=["priority", "start_time"]),
#         ]
    
#     def __str__(self):
#         return f"{self.title} on {self.channel.name} ({self.start_time})"
    
#     def clean(self):
#         """
#         Validate the schedule entry.
        
#         Raises:
#             ValidationError: If validation fails
#         """
#         super().clean()
        
#         # Validate time range
#         if self.start_time and self.end_time:
#             if self.start_time >= self.end_time:
#                 raise ValidationError({
#                     'end_time': _('End time must be after start time.')
#                 })
        
#         # Validate ad break settings
#         if self.allow_ads and self.ad_break_duration <= 0:
#             raise ValidationError({
#                 'ad_break_duration': _('Ad break duration must be positive if ads are allowed.')
#             })
        
#         # Validate priority
#         if self.priority <= 0:
#             raise ValidationError({
#                 'priority': _('Priority must be a positive integer.')
#             })
    
#     @property
#     def duration(self):
#         """
#         Get the scheduled duration in seconds.
        
#         Returns:
#             float: Duration in seconds, or 0 if times not set
#         """
#         if self.start_time and self.end_time:
#             return (self.end_time - self.start_time).total_seconds()
#         return 0
    
#     @property
#     def duration_minutes(self):
#         """Get the scheduled duration in minutes."""
#         return self.duration / 60
    
#     @property
#     def duration_hours(self):
#         """Get the scheduled duration in hours."""
#         return self.duration / 3600
    
#     @property
#     def is_currently_active(self):
#         """
#         Check if the schedule is currently active.
        
#         Returns:
#             bool: True if schedule is active and within time range
#         """
#         if not self.is_active:
#             return False
            
#         now = timezone.now()
#         return self.start_time <= now <= self.end_time
    
#     @property
#     def is_upcoming(self):
#         """Check if the schedule is upcoming (future)."""
#         now = timezone.now()
#         return self.is_active and self.start_time > now
    
#     @property
#     def is_past(self):
#         """Check if the schedule is in the past."""
#         now = timezone.now()
#         return self.end_time < now
    
#     @property
#     def actual_duration(self):
#         """
#         Get the actual duration based on actual start/end times.
        
#         Returns:
#             float: Actual duration in seconds, or None if not available
#         """
#         if self.actual_start_time and self.actual_end_time:
#             return (self.actual_end_time - self.actual_start_time).total_seconds()
#         return None
    
#     def mark_started(self, start_time=None):
#         """
#         Mark the schedule as started.
        
#         Args:
#             start_time: Optional custom start time, defaults to now
#         """
#         self.actual_start_time = start_time or timezone.now()
#         self.save(update_fields=['actual_start_time'])
    
#     def mark_ended(self, end_time=None):
#         """
#         Mark the schedule as ended.
        
#         Args:
#             end_time: Optional custom end time, defaults to now
#         """
#         self.actual_end_time = end_time or timezone.now()
#         self.save(update_fields=['actual_end_time'])
    
#     def get_overlapping_schedules(self):
#         """
#         Get other schedules that overlap with this one.
        
#         Returns:
#             QuerySet: Overlapping schedule entries for the same channel
#         """
#         return ChannelSchedule.objects.filter(
#             channel=self.channel,
#             is_active=True
#         ).exclude(
#             id=self.id
#         ).filter(
#             models.Q(
#                 start_time__lt=self.end_time,
#                 end_time__gt=self.start_time
#             )
#         )
    
#     def has_conflicts(self):
#         """
#         Check if this schedule has conflicts with other schedules.
        
#         Returns:
#             bool: True if there are conflicting schedules
#         """
#         return self.get_overlapping_schedules().exists()
    
#     def get_status(self):
#         """
#         Get the current status of this schedule.
        
#         Returns:
#             str: Current status (upcoming, active, ended, inactive)
#         """
#         if not self.is_active:
#             return 'inactive'
        
#         now = timezone.now()
        
#         if self.end_time < now:
#             return 'ended'
#         elif self.start_time <= now <= self.end_time:
#             return 'active'
#         else:
#             return 'upcoming'
    
#     def calculate_ad_opportunities(self):
#         """
#         Calculate ad insertion opportunities for this schedule.
        
#         Returns:
#             list: List of timestamps where ads can be inserted
#         """
#         if not self.allow_ads or self.duration <= 0:
#             return []
        
#         opportunities = []
#         duration_seconds = int(self.duration)
#         max_breaks = int(self.duration_hours * self.max_ad_breaks_per_hour)
        
#         if max_breaks <= 0:
#             return opportunities
        
#         # Calculate intervals between ad breaks
#         interval = duration_seconds / (max_breaks + 1)
        
#         for i in range(1, max_breaks + 1):
#             opportunity_time = self.start_time + timezone.timedelta(seconds=int(i * interval))
#             opportunities.append(opportunity_time)
        
#         return opportunities
    
#     def get_schedule_summary(self):
#         """
#         Get a summary of this schedule.
        
#         Returns:
#             dict: Summary information about the schedule
#         """
#         return {
#             'title': self.title,
#             'channel': self.channel.name,
#             'type': self.get_schedule_type_display(),
#             'start_time': self.start_time,
#             'end_time': self.end_time,
#             'duration_minutes': self.duration_minutes,
#             'status': self.get_status(),
#             'allow_ads': self.allow_ads,
#             'priority': self.priority,
#             'has_conflicts': self.has_conflicts(),
#         }