from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from apps.common.models import BaseModel


class ChannelZone(BaseModel):
    """Geographic zones for channel broadcasting."""
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=10, unique=True)
    description = models.TextField(blank=True)
    timezone = models.CharField(max_length=50, default="UTC")
    is_active = models.BooleanField(default=True)
    
    class Meta:
        db_table = "channel_zones"
        ordering = ["name"]
    
    def __str__(self):
        return f"{self.name} ({self.code})"


class ChannelCodec(BaseModel):
    """Video/Audio codec configurations for channels."""
    name = models.CharField(max_length=100)
    video_codec = models.CharField(max_length=50)
    audio_codec = models.CharField(max_length=50)
    resolution = models.CharField(max_length=20, blank=True)  # e.g., 1920x1080
    bitrate = models.PositiveIntegerField(help_text="Bitrate in kbps")
    frame_rate = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
    
    class Meta:
        db_table = "channel_codecs"
        ordering = ["name"]
    
    def __str__(self):
        return f"{self.name} ({self.video_codec}/{self.audio_codec})"


class Channel(BaseModel):
    """TV Channel model."""
    CHANNEL_TYPES = [
        ("tv", "Television"),
        ("radio", "Radio"),
        ("streaming", "Streaming"),
        ("ott", "Over-the-Top"),
    ]
    
    STATUS_CHOICES = [
        ("active", "Active"),
        ("inactive", "Inactive"),
        ("maintenance", "Maintenance"),
        ("testing", "Testing"),
    ]
    
    name = models.CharField(max_length=255)
    display_name = models.CharField(max_length=255, blank=True)
    channel_number = models.PositiveIntegerField(null=True, blank=True)
    channel_type = models.CharField(max_length=20, choices=CHANNEL_TYPES, default="tv")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="active")
    
    # Technical details
    stream_url = models.URLField(blank=True)
    backup_stream_url = models.URLField(blank=True)
    codec = models.ForeignKey(ChannelCodec, on_delete=models.SET_NULL, null=True, blank=True)
    zone = models.ForeignKey(ChannelZone, on_delete=models.SET_NULL, null=True, blank=True)
    
    # Branding
    logo = models.ImageField(upload_to="channels/logos/", blank=True, null=True)
    description = models.TextField(blank=True)
    website = models.URLField(blank=True)
    
    # Broadcasting details
    language = models.CharField(max_length=50, blank=True)
    category = models.CharField(max_length=100, blank=True)  # News, Sports, Entertainment, etc.
    target_audience = models.CharField(max_length=100, blank=True)
    
    # Ad insertion settings
    supports_dai = models.BooleanField(default=True, help_text="Dynamic Ad Insertion support")
    max_ad_duration = models.PositiveIntegerField(default=180, help_text="Maximum ad break duration in seconds")
    min_ad_gap = models.PositiveIntegerField(default=300, help_text="Minimum gap between ads in seconds")
    
    # Monitoring
    last_health_check = models.DateTimeField(null=True, blank=True)
    is_online = models.BooleanField(default=True)
    
    class Meta:
        db_table = "channels"
        ordering = ["channel_number", "name"]
        unique_together = ["channel_number", "zone"]
    
    def __str__(self):
        if self.channel_number:
            return f"{self.channel_number}. {self.display_name or self.name}"
        return self.display_name or self.name
    
    @property
    def is_active(self):
        return self.status == "active" and self.is_online
    
    def update_health_status(self, is_online=True):
        """Update channel health status."""
        self.is_online = is_online
        self.last_health_check = timezone.now()
        self.save(update_fields=["is_online", "last_health_check"])


class EPGProgram(BaseModel):
    """Electronic Program Guide entries."""
    PROGRAM_TYPES = [
        ("movie", "Movie"),
        ("series", "TV Series"),
        ("news", "News"),
        ("sports", "Sports"),
        ("documentary", "Documentary"),
        ("entertainment", "Entertainment"),
        ("kids", "Kids"),
        ("music", "Music"),
        ("other", "Other"),
    ]
    
    channel = models.ForeignKey(Channel, on_delete=models.CASCADE, related_name="programs")
    
    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    program_type = models.CharField(max_length=20, choices=PROGRAM_TYPES, default="other")
    
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    duration = models.PositiveIntegerField(help_text="Duration in minutes")
    
    # Content details
    season_number = models.PositiveIntegerField(null=True, blank=True)
    episode_number = models.PositiveIntegerField(null=True, blank=True)
    original_air_date = models.DateField(null=True, blank=True)
    
    # Ratings and content
    content_rating = models.CharField(max_length=10, blank=True)  # G, PG, PG-13, etc.
    language = models.CharField(max_length=50, blank=True)
    subtitles_available = models.BooleanField(default=False)
    
    # Ad insertion opportunities
    has_ad_breaks = models.BooleanField(default=True)
    ad_break_positions = models.JSONField(default=list, blank=True)  # List of seconds where ads can be inserted
    
    class Meta:
        db_table = "epg_programs"
        ordering = ["channel", "start_time"]
        indexes = [
            models.Index(fields=["channel", "start_time"]),
            models.Index(fields=["start_time", "end_time"]),
        ]
    
    def __str__(self):
        return f"{self.title} on {self.channel.name} at {self.start_time}"
    
    @property
    def is_currently_airing(self):
        now = timezone.now()
        return self.start_time <= now <= self.end_time
    
    def get_ad_opportunities(self):
        """Get available ad insertion opportunities."""
        if not self.has_ad_breaks:
            return []
        
        # Default ad breaks at beginning, middle, and end
        if not self.ad_break_positions:
            duration_seconds = self.duration * 60
            return [0, duration_seconds // 2, duration_seconds - 30]
        
        return self.ad_break_positions


class Jingle(BaseModel):
    """Channel jingles and station IDs."""
    JINGLE_TYPES = [
        ("station_id", "Station ID"),
        ("bumper", "Bumper"),
        ("promo", "Promo"),
        ("transition", "Transition"),
        ("commercial_break", "Commercial Break"),
    ]
    
    channel = models.ForeignKey(Channel, on_delete=models.CASCADE, related_name="jingles")
    
    name = models.CharField(max_length=255)
    jingle_type = models.CharField(max_length=20, choices=JINGLE_TYPES)
    file = models.FileField(upload_to="jingles/")
    duration = models.PositiveIntegerField(help_text="Duration in seconds")
    
    # Usage settings
    is_active = models.BooleanField(default=True)
    priority = models.PositiveIntegerField(default=1, help_text="Higher number = higher priority")
    
    # Scheduling
    start_date = models.DateField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)
    time_slots = models.JSONField(default=list, blank=True)  # List of time ranges when this jingle can play
    
    # Usage tracking
    play_count = models.PositiveIntegerField(default=0)
    last_played = models.DateTimeField(null=True, blank=True)
    
    class Meta:
        db_table = "jingles"
        ordering = ["channel", "-priority", "name"]
    
    def __str__(self):
        return f"{self.name} ({self.channel.name})"
    
    def can_play_now(self):
        """Check if jingle can be played at current time."""
        if not self.is_active:
            return False
        
        now = timezone.now()
        
        # Check date range
        if self.start_date and now.date() < self.start_date:
            return False
        if self.end_date and now.date() > self.end_date:
            return False
        
        # Check time slots
        if self.time_slots:
            current_time = now.time()
            for slot in self.time_slots:
                start_time = timezone.datetime.strptime(slot["start"], "%H:%M").time()
                end_time = timezone.datetime.strptime(slot["end"], "%H:%M").time()
                if start_time <= current_time <= end_time:
                    return True
            return False
        
        return True
    
    def mark_played(self):
        """Mark jingle as played."""
        self.play_count += 1
        self.last_played = timezone.now()
        self.save(update_fields=["play_count", "last_played"])


class ChannelSchedule(BaseModel):
    """Channel broadcasting schedule."""
    SCHEDULE_TYPES = [
        ("regular", "Regular Programming"),
        ("special", "Special Event"),
        ("maintenance", "Maintenance"),
        ("test", "Test Broadcast"),
    ]
    
    channel = models.ForeignKey(Channel, on_delete=models.CASCADE, related_name="schedules")
    
    title = models.CharField(max_length=255)
    schedule_type = models.CharField(max_length=20, choices=SCHEDULE_TYPES, default="regular")
    
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    
    # Content details
    description = models.TextField(blank=True)
    content_url = models.URLField(blank=True)
    backup_content_url = models.URLField(blank=True)
    
    # Ad settings
    allow_ads = models.BooleanField(default=True)
    ad_break_duration = models.PositiveIntegerField(default=120, help_text="Ad break duration in seconds")
    
    # Status
    is_active = models.BooleanField(default=True)
    
    class Meta:
        db_table = "channel_schedules"
        ordering = ["channel", "start_time"]
    
    def __str__(self):
        return f"{self.title} on {self.channel.name}"
    
    @property
    def is_currently_active(self):
        now = timezone.now()
        return self.is_active and self.start_time <= now <= self.end_time