from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.core.validators import MinValueValidator, MaxValueValidator
from apps.common.models import BaseModel
from apps.channels.models import Channel
from apps.campaigns.models import Campaign, Creative


class PlaylistTemplate(BaseModel):
    """Template for creating playlists with predefined structure."""
    
    TEMPLATE_TYPES = [
        ("daily", "Daily Schedule"),
        ("weekly", "Weekly Schedule"),
        ("special", "Special Event"),
        ("holiday", "Holiday Schedule"),
        ("custom", "Custom Template"),
    ]
    
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    template_type = models.CharField(max_length=20, choices=TEMPLATE_TYPES, default="daily")
    duration_minutes = models.PositiveIntegerField(help_text="Template duration in minutes")
    
    # Template settings
    ad_break_interval = models.PositiveIntegerField(
        default=15,
        help_text="Minutes between ad breaks"
    )
    max_ad_duration = models.PositiveIntegerField(
        default=180,
        help_text="Maximum ad duration per break in seconds"
    )
    
    # Content ratios (percentages)
    content_ratio = models.PositiveIntegerField(
        default=80,
        validators=[MinValueValidator(1), MaxValueValidator(100)],
        help_text="Percentage of content vs ads"
    )
    
    is_active = models.BooleanField(default=True)
    created_by = models.ForeignKey("accounts.User", on_delete=models.SET_NULL, null=True)
    
    class Meta:
        ordering = ["name"]
    
    def __str__(self):
        return self.name
    
    @property
    def ad_ratio(self):
        """Calculate ad ratio from content ratio."""
        return 100 - self.content_ratio
    
    def get_total_ad_time(self):
        """Calculate total ad time for this template."""
        return (self.duration_minutes * 60 * self.ad_ratio) // 100


class Playlist(BaseModel):
    """Main playlist model for scheduling content and ads."""
    
    STATUS_CHOICES = [
        ("draft", "Draft"),
        ("scheduled", "Scheduled"),
        ("active", "Active"),
        ("completed", "Completed"),
        ("cancelled", "Cancelled"),
    ]
    
    PRIORITY_CHOICES = [
        (1, "Low"),
        (2, "Normal"),
        (3, "High"),
        (4, "Critical"),
    ]
    
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    channel = models.ForeignKey(Channel, on_delete=models.CASCADE, related_name="playlists")
    template = models.ForeignKey(
        PlaylistTemplate, 
        on_delete=models.SET_NULL, 
        null=True, 
        blank=True,
        related_name="playlists"
    )
    
    # Scheduling
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="draft")
    priority = models.PositiveIntegerField(choices=PRIORITY_CHOICES, default=2)
    
    # Settings
    auto_fill_gaps = models.BooleanField(
        default=True,
        help_text="Automatically fill gaps with filler content"
    )
    allow_overrun = models.BooleanField(
        default=False,
        help_text="Allow playlist to run over scheduled end time"
    )
    loop_content = models.BooleanField(
        default=False,
        help_text="Loop content if playlist is shorter than scheduled time"
    )
    
    # Metadata
    created_by = models.ForeignKey("accounts.User", on_delete=models.SET_NULL, null=True)
    approved_by = models.ForeignKey(
        "accounts.User", 
        on_delete=models.SET_NULL, 
        null=True, 
        blank=True,
        related_name="approved_playlists"
    )
    approved_at = models.DateTimeField(null=True, blank=True)
    
    # Statistics
    total_duration = models.PositiveIntegerField(default=0, help_text="Total duration in seconds")
    content_duration = models.PositiveIntegerField(default=0, help_text="Content duration in seconds")
    ad_duration = models.PositiveIntegerField(default=0, help_text="Ad duration in seconds")
    
    class Meta:
        ordering = ["-start_time"]
        indexes = [
            models.Index(fields=["channel", "start_time"]),
            models.Index(fields=["status", "start_time"]),
        ]
    
    def __str__(self):
        return f"{self.name} - {self.channel.name}"
    
    @property
    def duration_minutes(self):
        """Get playlist duration in minutes."""
        if self.start_time and self.end_time:
            delta = self.end_time - self.start_time
            return int(delta.total_seconds() / 60)
        return 0
    
    @property
    def is_active(self):
        """Check if playlist is currently active."""
        now = timezone.now()
        return (
            self.status == "active" and
            self.start_time <= now <= self.end_time
        )
    
    @property
    def is_upcoming(self):
        """Check if playlist is upcoming."""
        return self.start_time > timezone.now()
    
    def calculate_durations(self):
        """Calculate total, content, and ad durations."""
        items = self.items.all()
        
        total = sum(item.duration for item in items)
        content = sum(item.duration for item in items if item.item_type == "content")
        ads = sum(item.duration for item in items if item.item_type == "ad")
        
        self.total_duration = total
        self.content_duration = content
        self.ad_duration = ads
        self.save(update_fields=["total_duration", "content_duration", "ad_duration"])
    
    def approve(self, user):
        """Approve the playlist."""
        self.approved_by = user
        self.approved_at = timezone.now()
        self.status = "scheduled"
        self.save()
    
    def activate(self):
        """Activate the playlist."""
        self.status = "active"
        self.save()
    
    def complete(self):
        """Mark playlist as completed."""
        self.status = "completed"
        self.save()


class PlaylistItem(BaseModel):
    """Individual items within a playlist."""
    
    ITEM_TYPES = [
        ("content", "Content"),
        ("ad", "Advertisement"),
        ("jingle", "Jingle"),
        ("filler", "Filler"),
        ("break", "Break"),
    ]
    
    playlist = models.ForeignKey(Playlist, on_delete=models.CASCADE, related_name="items")
    item_type = models.CharField(max_length=20, choices=ITEM_TYPES)
    
    # Content references
    campaign = models.ForeignKey(
        Campaign, 
        on_delete=models.CASCADE, 
        null=True, 
        blank=True,
        help_text="For ad items"
    )
    creative = models.ForeignKey(
        Creative, 
        on_delete=models.CASCADE, 
        null=True, 
        blank=True,
        help_text="For ad items"
    )
    
    # Item details
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    file_path = models.CharField(max_length=500, blank=True)
    duration = models.PositiveIntegerField(help_text="Duration in seconds")
    
    # Scheduling
    start_offset = models.PositiveIntegerField(
        default=0,
        help_text="Start time offset from playlist start in seconds"
    )
    order = models.PositiveIntegerField(default=0)
    
    # Playback settings
    volume_level = models.FloatField(
        default=1.0,
        validators=[MinValueValidator(0.0), MaxValueValidator(2.0)],
        help_text="Volume level (0.0 to 2.0)"
    )
    fade_in = models.PositiveIntegerField(
        default=0,
        help_text="Fade in duration in milliseconds"
    )
    fade_out = models.PositiveIntegerField(
        default=0,
        help_text="Fade out duration in milliseconds"
    )
    
    # Metadata
    is_mandatory = models.BooleanField(
        default=False,
        help_text="Cannot be skipped or replaced"
    )
    can_overlap = models.BooleanField(
        default=False,
        help_text="Can overlap with other items"
    )
    
    class Meta:
        ordering = ["order", "start_offset"]
        indexes = [
            models.Index(fields=["playlist", "order"]),
            models.Index(fields=["item_type", "start_offset"]),
        ]
    
    def __str__(self):
        return f"{self.name} ({self.get_item_type_display()})"
    
    @property
    def end_offset(self):
        """Calculate end time offset."""
        return self.start_offset + self.duration
    
    @property
    def start_time(self):
        """Calculate actual start time."""
        return self.playlist.start_time + timezone.timedelta(seconds=self.start_offset)
    
    @property
    def end_time(self):
        """Calculate actual end time."""
        return self.start_time + timezone.timedelta(seconds=self.duration)


class PlaylistExecution(BaseModel):
    """Track playlist execution and playback status."""
    
    STATUS_CHOICES = [
        ("pending", "Pending"),
        ("playing", "Playing"),
        ("paused", "Paused"),
        ("completed", "Completed"),
        ("failed", "Failed"),
        ("skipped", "Skipped"),
    ]
    
    playlist = models.ForeignKey(Playlist, on_delete=models.CASCADE, related_name="executions")
    playlist_item = models.ForeignKey(
        PlaylistItem, 
        on_delete=models.CASCADE, 
        null=True, 
        blank=True,
        related_name="executions"
    )
    
    # Execution details
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="pending")
    started_at = models.DateTimeField(null=True, blank=True)
    completed_at = models.DateTimeField(null=True, blank=True)
    
    # Playback info
    actual_duration = models.PositiveIntegerField(
        default=0,
        help_text="Actual playback duration in seconds"
    )
    position = models.PositiveIntegerField(
        default=0,
        help_text="Current playback position in seconds"
    )
    
    # Error handling
    error_message = models.TextField(blank=True)
    retry_count = models.PositiveIntegerField(default=0)
    
    class Meta:
        ordering = ["-started_at"]
        indexes = [
            models.Index(fields=["playlist", "status"]),
            models.Index(fields=["started_at"]),
        ]
    
    def __str__(self):
        item_name = self.playlist_item.name if self.playlist_item else "Full Playlist"
        return f"{self.playlist.name} - {item_name}"
    
    def start_playback(self):
        """Mark playback as started."""
        self.status = "playing"
        self.started_at = timezone.now()
        self.save()
    
    def complete_playback(self):
        """Mark playback as completed."""
        self.status = "completed"
        self.completed_at = timezone.now()
        if self.started_at:
            delta = self.completed_at - self.started_at
            self.actual_duration = int(delta.total_seconds())
        self.save()
    
    def fail_playback(self, error_message):
        """Mark playback as failed."""
        self.status = "failed"
        self.error_message = error_message
        self.completed_at = timezone.now()
        self.save()


class PlaylistConflict(BaseModel):
    """Track scheduling conflicts between playlists."""
    
    CONFLICT_TYPES = [
        ("overlap", "Time Overlap"),
        ("resource", "Resource Conflict"),
        ("priority", "Priority Conflict"),
        ("content", "Content Conflict"),
    ]
    
    SEVERITY_LEVELS = [
        ("low", "Low"),
        ("medium", "Medium"),
        ("high", "High"),
        ("critical", "Critical"),
    ]
    
    playlist_a = models.ForeignKey(
        Playlist, 
        on_delete=models.CASCADE, 
        related_name="conflicts_as_a"
    )
    playlist_b = models.ForeignKey(
        Playlist, 
        on_delete=models.CASCADE, 
        related_name="conflicts_as_b"
    )
    
    conflict_type = models.CharField(max_length=20, choices=CONFLICT_TYPES)
    severity = models.CharField(max_length=20, choices=SEVERITY_LEVELS, default="medium")
    
    description = models.TextField()
    is_resolved = models.BooleanField(default=False)
    resolved_by = models.ForeignKey(
        "accounts.User", 
        on_delete=models.SET_NULL, 
        null=True, 
        blank=True
    )
    resolved_at = models.DateTimeField(null=True, blank=True)
    resolution_notes = models.TextField(blank=True)
    
    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["playlist_a", "is_resolved"]),
            models.Index(fields=["conflict_type", "severity"]),
        ]
    
    def __str__(self):
        return f"Conflict: {self.playlist_a.name} vs {self.playlist_b.name}"
    
    def resolve(self, user, notes=""):
        """Mark conflict as resolved."""
        self.is_resolved = True
        self.resolved_by = user
        self.resolved_at = timezone.now()
        self.resolution_notes = notes
        self.save()