from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.contrib import messages
from django.http import JsonResponse
from django.core.paginator import Paginator
from django.db.models import Q, Count, Sum, Avg
from django.utils import timezone
from django.views.decorators.http import require_http_methods
from django.db import transaction
from django.urls import reverse_lazy, reverse
from datetime import datetime, timedelta
import json
import logging

from apps.playlists.models import PlaylistTemplate, Playlist, PlaylistItem
from apps.campaigns.models import Campaign, AdSpot
from apps.channels.models import Channel
from apps.core.models import ActivityLog

logger = logging.getLogger(__name__)


# Dashboard View
@login_required
def dashboard(request):
    """
    Playlists management dashboard with statistics
    """
    # Get dashboard statistics
    total_templates = PlaylistTemplate.objects.count()
    active_templates = PlaylistTemplate.objects.filter(is_active=True).count()
    total_playlists = Playlist.objects.count()
    active_playlists = Playlist.objects.filter(is_active=True).count()
    
    # Recent playlists
    recent_playlists = Playlist.objects.select_related(
        'template', 'channel'
    ).order_by('-created_at')[:5]
    
    # Playlist statistics
    playlist_stats = Playlist.objects.aggregate(
        avg_items=Avg('items__id'),
        total_duration=Sum('total_duration')
    )
    
    # Recent activity
    recent_activity = ActivityLog.objects.filter(
        content_type__model__in=['playlist', 'playlisttemplate', 'playlistitem']
    ).select_related('user').order_by('-created_at')[:10]
    
    context = {
        'total_templates': total_templates,
        'active_templates': active_templates,
        'total_playlists': total_playlists,
        'active_playlists': active_playlists,
        'recent_playlists': recent_playlists,
        'playlist_stats': playlist_stats,
        'recent_activity': recent_activity,
    }
    
    return render(request, 'playlists/dashboard.html', context)


# Playlist Template Views
class PlaylistTemplateListView(LoginRequiredMixin, ListView):
    """
    List all playlist templates
    """
    model = PlaylistTemplate
    template_name = 'playlists/template_list.html'
    context_object_name = 'templates'
    paginate_by = 20
    
    def get_queryset(self):
        queryset = PlaylistTemplate.objects.annotate(
            playlist_count=Count('playlists')
        )
        
        # Filter by active status
        is_active = self.request.GET.get('active')
        if is_active:
            queryset = queryset.filter(is_active=is_active == 'true')
        
        # Search
        search = self.request.GET.get('search')
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) |
                Q(description__icontains=search)
            )
        
        return queryset.order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filters'] = {
            'active': self.request.GET.get('active', ''),
            'search': self.request.GET.get('search', ''),
        }
        return context


class PlaylistTemplateDetailView(LoginRequiredMixin, DetailView):
    """
    Playlist template detail view with related playlists
    """
    model = PlaylistTemplate
    template_name = 'playlists/template_detail.html'
    context_object_name = 'template'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        template = self.get_object()
        
        # Get related playlists
        playlists = Playlist.objects.filter(
            template=template
        ).select_related('channel').order_by('-created_at')
        
        context['playlists'] = playlists
        context['playlist_count'] = playlists.count()
        context['active_playlists'] = playlists.filter(is_active=True).count()
        
        return context


class PlaylistTemplateCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    """
    Create new playlist template
    """
    model = PlaylistTemplate
    fields = ['name', 'description', 'template_data', 'default_duration', 'is_active']
    template_name = 'playlists/template_form.html'
    permission_required = 'playlists.add_playlisttemplate'
    success_url = reverse_lazy('playlists:template_list')
    
    def form_valid(self, form):
        # Log activity
        ActivityLog.objects.create(
            user=self.request.user,
            action='create',
            content_object=form.instance,
            description=f'Created playlist template: {form.instance.name}'
        )
        
        messages.success(self.request, 'Playlist template created successfully!')
        return super().form_valid(form)


class PlaylistTemplateUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    """
    Update existing playlist template
    """
    model = PlaylistTemplate
    fields = ['name', 'description', 'template_data', 'default_duration', 'is_active']
    template_name = 'playlists/template_form.html'
    permission_required = 'playlists.change_playlisttemplate'
    
    def get_success_url(self):
        return reverse('playlists:template_detail', kwargs={'pk': self.object.pk})
    
    def form_valid(self, form):
        # Log activity
        ActivityLog.objects.create(
            user=self.request.user,
            action='update',
            content_object=form.instance,
            description=f'Updated playlist template: {form.instance.name}'
        )
        
        messages.success(self.request, 'Playlist template updated successfully!')
        return super().form_valid(form)


class PlaylistTemplateDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
    """
    Delete playlist template
    """
    model = PlaylistTemplate
    template_name = 'playlists/template_confirm_delete.html'
    permission_required = 'playlists.delete_playlisttemplate'
    success_url = reverse_lazy('playlists:template_list')
    
    def delete(self, request, *args, **kwargs):
        template = self.get_object()
        
        # Log activity
        ActivityLog.objects.create(
            user=request.user,
            action='delete',
            content_object=template,
            description=f'Deleted playlist template: {template.name}'
        )
        
        messages.success(request, 'Playlist template deleted successfully!')
        return super().delete(request, *args, **kwargs)


# Playlist Views
class PlaylistListView(LoginRequiredMixin, ListView):
    """
    List all playlists
    """
    model = Playlist
    template_name = 'playlists/playlist_list.html'
    context_object_name = 'playlists'
    paginate_by = 20
    
    def get_queryset(self):
        queryset = Playlist.objects.select_related(
            'template', 'channel'
        ).annotate(
            item_count=Count('items')
        )
        
        # Filter by template
        template_id = self.request.GET.get('template')
        if template_id:
            queryset = queryset.filter(template_id=template_id)
        
        # Filter by channel
        channel_id = self.request.GET.get('channel')
        if channel_id:
            queryset = queryset.filter(channel_id=channel_id)
        
        # Filter by active status
        is_active = self.request.GET.get('active')
        if is_active:
            queryset = queryset.filter(is_active=is_active == 'true')
        
        # Filter by date
        date = self.request.GET.get('date')
        if date:
            try:
                date_obj = datetime.strptime(date, '%Y-%m-%d').date()
                queryset = queryset.filter(schedule_date=date_obj)
            except ValueError:
                pass
        
        # Search
        search = self.request.GET.get('search')
        if search:
            queryset = queryset.filter(
                Q(name__icontains=search) |
                Q(description__icontains=search)
            )
        
        return queryset.order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['templates'] = PlaylistTemplate.objects.filter(is_active=True).order_by('name')
        context['channels'] = Channel.objects.filter(status='active').order_by('name')
        context['filters'] = {
            'template': self.request.GET.get('template', ''),
            'channel': self.request.GET.get('channel', ''),
            'active': self.request.GET.get('active', ''),
            'date': self.request.GET.get('date', ''),
            'search': self.request.GET.get('search', ''),
        }
        return context


class PlaylistDetailView(LoginRequiredMixin, DetailView):
    """
    Playlist detail view with items
    """
    model = Playlist
    template_name = 'playlists/playlist_detail.html'
    context_object_name = 'playlist'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        playlist = self.get_object()
        
        # Get playlist items
        items = PlaylistItem.objects.filter(
            playlist=playlist
        ).select_related('adspot', 'campaign').order_by('order')
        
        context['items'] = items
        context['item_count'] = items.count()
        context['total_duration'] = sum(item.duration for item in items if item.duration)
        
        return context


class PlaylistCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    """
    Create new playlist
    """
    model = Playlist
    fields = ['name', 'description', 'template', 'channel', 'schedule_date', 
              'start_time', 'end_time', 'total_duration', 'is_active']
    template_name = 'playlists/playlist_form.html'
    permission_required = 'playlists.add_playlist'
    
    def get_success_url(self):
        return reverse('playlists:playlist_detail', kwargs={'pk': self.object.pk})
    
    def form_valid(self, form):
        # Log activity
        ActivityLog.objects.create(
            user=self.request.user,
            action='create',
            content_object=form.instance,
            description=f'Created playlist: {form.instance.name}'
        )
        
        messages.success(self.request, 'Playlist created successfully!')
        return super().form_valid(form)


class PlaylistUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    """
    Update existing playlist
    """
    model = Playlist
    fields = ['name', 'description', 'template', 'channel', 'schedule_date', 
              'start_time', 'end_time', 'total_duration', 'is_active']
    template_name = 'playlists/playlist_form.html'
    permission_required = 'playlists.change_playlist'
    
    def get_success_url(self):
        return reverse('playlists:playlist_detail', kwargs={'pk': self.object.pk})
    
    def form_valid(self, form):
        # Log activity
        ActivityLog.objects.create(
            user=self.request.user,
            action='update',
            content_object=form.instance,
            description=f'Updated playlist: {form.instance.name}'
        )
        
        messages.success(self.request, 'Playlist updated successfully!')
        return super().form_valid(form)


class PlaylistDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
    """
    Delete playlist
    """
    model = Playlist
    template_name = 'playlists/playlist_confirm_delete.html'
    permission_required = 'playlists.delete_playlist'
    success_url = reverse_lazy('playlists:playlist_list')
    
    def delete(self, request, *args, **kwargs):
        playlist = self.get_object()
        
        # Log activity
        ActivityLog.objects.create(
            user=request.user,
            action='delete',
            content_object=playlist,
            description=f'Deleted playlist: {playlist.name}'
        )
        
        messages.success(request, 'Playlist deleted successfully!')
        return super().delete(request, *args, **kwargs)


# Playlist Item Views
class PlaylistItemListView(LoginRequiredMixin, ListView):
    """
    List all playlist items
    """
    model = PlaylistItem
    template_name = 'playlists/item_list.html'
    context_object_name = 'items'
    paginate_by = 20
    
    def get_queryset(self):
        queryset = PlaylistItem.objects.select_related(
            'playlist', 'adspot', 'campaign'
        )
        
        # Filter by playlist
        playlist_id = self.request.GET.get('playlist')
        if playlist_id:
            queryset = queryset.filter(playlist_id=playlist_id)
        
        # Filter by campaign
        campaign_id = self.request.GET.get('campaign')
        if campaign_id:
            queryset = queryset.filter(campaign_id=campaign_id)
        
        # Search
        search = self.request.GET.get('search')
        if search:
            queryset = queryset.filter(
                Q(playlist__name__icontains=search) |
                Q(adspot__name__icontains=search) |
                Q(campaign__name__icontains=search)
            )
        
        return queryset.order_by('playlist', 'order')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['playlists'] = Playlist.objects.filter(is_active=True).order_by('name')
        context['campaigns'] = Campaign.objects.filter(status='active').order_by('name')
        context['filters'] = {
            'playlist': self.request.GET.get('playlist', ''),
            'campaign': self.request.GET.get('campaign', ''),
            'search': self.request.GET.get('search', ''),
        }
        return context


class PlaylistItemDetailView(LoginRequiredMixin, DetailView):
    """
    Playlist item detail view
    """
    model = PlaylistItem
    template_name = 'playlists/item_detail.html'
    context_object_name = 'item'


class PlaylistItemCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    """
    Create new playlist item
    """
    model = PlaylistItem
    fields = ['playlist', 'adspot', 'campaign', 'order', 'duration', 'start_time']
    template_name = 'playlists/item_form.html'
    permission_required = 'playlists.add_playlistitem'
    
    def get_success_url(self):
        return reverse('playlists:item_detail', kwargs={'pk': self.object.pk})
    
    def form_valid(self, form):
        # Log activity
        ActivityLog.objects.create(
            user=self.request.user,
            action='create',
            content_object=form.instance,
            description=f'Created playlist item for: {form.instance.playlist.name}'
        )
        
        messages.success(self.request, 'Playlist item created successfully!')
        return super().form_valid(form)


class PlaylistItemUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    """
    Update existing playlist item
    """
    model = PlaylistItem
    fields = ['playlist', 'adspot', 'campaign', 'order', 'duration', 'start_time']
    template_name = 'playlists/item_form.html'
    permission_required = 'playlists.change_playlistitem'
    
    def get_success_url(self):
        return reverse('playlists:item_detail', kwargs={'pk': self.object.pk})
    
    def form_valid(self, form):
        # Log activity
        ActivityLog.objects.create(
            user=self.request.user,
            action='update',
            content_object=form.instance,
            description=f'Updated playlist item for: {form.instance.playlist.name}'
        )
        
        messages.success(self.request, 'Playlist item updated successfully!')
        return super().form_valid(form)


class PlaylistItemDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
    """
    Delete playlist item
    """
    model = PlaylistItem
    template_name = 'playlists/item_confirm_delete.html'
    permission_required = 'playlists.delete_playlistitem'
    success_url = reverse_lazy('playlists:item_list')
    
    def delete(self, request, *args, **kwargs):
        item = self.get_object()
        
        # Log activity
        ActivityLog.objects.create(
            user=request.user,
            action='delete',
            content_object=item,
            description=f'Deleted playlist item from: {item.playlist.name}'
        )
        
        messages.success(request, 'Playlist item deleted successfully!')
        return super().delete(request, *args, **kwargs)


# Utility Functions
@login_required
@require_http_methods(["POST"])
def playlist_activate(request, playlist_id):
    """
    Activate a playlist
    """
    playlist = get_object_or_404(Playlist, id=playlist_id)
    
    playlist.is_active = True
    playlist.save()
    
    # Log activity
    ActivityLog.objects.create(
        user=request.user,
        action='activate',
        content_object=playlist,
        description=f'Activated playlist: {playlist.name}'
    )
    
    messages.success(request, f'Playlist "{playlist.name}" activated successfully!')
    return redirect('playlists:playlist_detail', pk=playlist.id)


@login_required
@require_http_methods(["POST"])
def playlist_deactivate(request, playlist_id):
    """
    Deactivate a playlist
    """
    playlist = get_object_or_404(Playlist, id=playlist_id)
    
    playlist.is_active = False
    playlist.save()
    
    # Log activity
    ActivityLog.objects.create(
        user=request.user,
        action='deactivate',
        content_object=playlist,
        description=f'Deactivated playlist: {playlist.name}'
    )
    
    messages.success(request, f'Playlist "{playlist.name}" deactivated successfully!')
    return redirect('playlists:playlist_detail', pk=playlist.id)


@login_required
@require_http_methods(["POST"])
def playlist_duplicate(request, playlist_id):
    """
    Duplicate a playlist
    """
    original_playlist = get_object_or_404(Playlist, id=playlist_id)
    
    # Create duplicate playlist
    duplicate_playlist = Playlist.objects.create(
        name=f"{original_playlist.name} (Copy)",
        description=original_playlist.description,
        template=original_playlist.template,
        channel=original_playlist.channel,
        schedule_date=original_playlist.schedule_date,
        start_time=original_playlist.start_time,
        end_time=original_playlist.end_time,
        total_duration=original_playlist.total_duration,
        is_active=False  # Start as inactive
    )
    
    # Duplicate playlist items
    for item in original_playlist.items.all():
        PlaylistItem.objects.create(
            playlist=duplicate_playlist,
            adspot=item.adspot,
            campaign=item.campaign,
            order=item.order,
            duration=item.duration,
            start_time=item.start_time
        )
    
    # Log activity
    ActivityLog.objects.create(
        user=request.user,
        action='duplicate',
        content_object=duplicate_playlist,
        description=f'Duplicated playlist: {original_playlist.name}'
    )
    
    messages.success(request, f'Playlist "{original_playlist.name}" duplicated successfully!')
    return redirect('playlists:playlist_detail', pk=duplicate_playlist.id)


# AJAX Views
@login_required
def playlist_search_ajax(request):
    """
    AJAX endpoint for playlist search
    """
    query = request.GET.get('q', '')
    playlists = Playlist.objects.filter(
        Q(name__icontains=query) |
        Q(description__icontains=query)
    ).values('id', 'name', 'schedule_date')[:10]
    
    return JsonResponse({
        'status': 'success',
        'playlists': list(playlists)
    })


@login_required
def template_search_ajax(request):
    """
    AJAX endpoint for template search
    """
    query = request.GET.get('q', '')
    templates = PlaylistTemplate.objects.filter(
        Q(name__icontains=query) |
        Q(description__icontains=query),
        is_active=True
    ).values('id', 'name', 'default_duration')[:10]
    
    return JsonResponse({
        'status': 'success',
        'templates': list(templates)
    })


@login_required
def playlist_stats_ajax(request, playlist_id):
    """
    AJAX endpoint for playlist statistics
    """
    try:
        playlist = Playlist.objects.get(id=playlist_id)
        
        # Get playlist statistics
        items = PlaylistItem.objects.filter(playlist=playlist)
        
        stats = {
            'total_items': items.count(),
            'total_duration': sum(item.duration for item in items if item.duration),
            'campaigns': items.values('campaign__name').distinct().count(),
            'adspots': items.values('adspot__name').distinct().count(),
        }
        
        # Item breakdown by campaign
        campaign_breakdown = items.values('campaign__name').annotate(
            count=Count('id')
        ).order_by('-count')
        
        return JsonResponse({
            'status': 'success',
            'data': {
                'stats': stats,
                'campaign_breakdown': list(campaign_breakdown),
                'is_active': playlist.is_active,
            }
        })
        
    except Playlist.DoesNotExist:
        return JsonResponse({
            'status': 'error',
            'message': 'Playlist not found'
        }, status=404)
    except Exception as e:
        logger.error(f'Error getting playlist stats: {str(e)}')
        return JsonResponse({
            'status': 'error',
            'message': 'Internal server error'
        }, status=500)
    
@login_required
def activate_playlist(request, playlist_id):
    """
    AJAX endpoint to activate a playlist
    """
    try:
        playlist = Playlist.objects.get(id=playlist_id)
        playlist.is_active = True
        playlist.save()
        
        # Log activity
        ActivityLog.objects.create(
            user=request.user,
            action='activate',
            content_object=playlist,
            description=f'Activated playlist: {playlist.name}'
        )
        
        return JsonResponse({
            'status': 'success',
            'message': f'Playlist "{playlist.name}" activated successfully!'
        })
    except Playlist.DoesNotExist:
        return JsonResponse({
            'status': 'error',
            'message': 'Playlist not found'
        }, status=404) 

@login_required
def duplicate_playlist(request, playlist_id):
    """
    AJAX endpoint to duplicate a playlist
    """
    try:
        original_playlist = Playlist.objects.get(id=playlist_id)
        
        # Create duplicate playlist
        duplicate_playlist = Playlist.objects.create(
            name=f"{original_playlist.name} (Copy)",
            description=original_playlist.description,
            template=original_playlist.template,
            channel=original_playlist.channel,
            schedule_date=original_playlist.schedule_date,
            start_time=original_playlist.start_time,
            end_time=original_playlist.end_time,
            total_duration=original_playlist.total_duration,
            is_active=False  # Start as inactive
        )
        
        # Duplicate playlist items
        for item in original_playlist.items.all():
            PlaylistItem.objects.create(
                playlist=duplicate_playlist,
                adspot=item.adspot,
                campaign=item.campaign,
                order=item.order,
                duration=item.duration,
                start_time=item.start_time
            )
        
        # Log activity
        ActivityLog.objects.create(
            user=request.user,
            action='duplicate',
            content_object=duplicate_playlist,
            description=f'Duplicated playlist: {original_playlist.name}'
        )
        
        messages.success(request, f'Playlist "{original_playlist.name}" duplicated successfully!')
        return redirect('playlists:playlist_detail', pk=duplicate_playlist.id)
    except Playlist.DoesNotExist:
        return JsonResponse({
            'status': 'error',
            'message': 'Playlist not found'
        }, status=404)
    except Exception as e:
        logger.error(f'Error duplicating playlist: {str(e)}')
        return JsonResponse({
            'status': 'error',
            'message': 'Internal server error'
        }, status=500) 

@login_required
def deactivate_playlist(request, playlist_id):
    """
    AJAX endpoint to deactivate a playlist
    """
    try:
        playlist = Playlist.objects.get(id=playlist_id)
        playlist.is_active = False
        playlist.save()
        
        # Log activity
        ActivityLog.objects.create(
            user=request.user,
            action='deactivate',
            content_object=playlist,
            description=f'Deactivated playlist: {playlist.name}'
        )
        
        return JsonResponse({
            'status': 'success',
            'message': f'Playlist "{playlist.name}" deactivated successfully!'
        })
    except Playlist.DoesNotExist:
        return JsonResponse({
            'status': 'error',
            'message': 'Playlist not found'
        }, status=404)
    except Exception as e:
        logger.error(f'Error deactivating playlist: {str(e)}')
        return JsonResponse({
            'status': 'error',
            'message': 'Internal server error'
        }, status=500) 
