

from email import message
import os  
import pytz
import json 
import requests
import datetime  

from django.views import View  
from django.db import connection
from django.utils import timezone
from django.db import transaction
from django.contrib import messages
from django.urls import reverse_lazy, reverse
from django.db.models import Q, Count, Max, Min
from django.http import HttpResponse, JsonResponse  
from django.core.exceptions import PermissionDenied 
from django.utils.decorators import method_decorator 
from django.views.decorators.csrf import csrf_protect
from django.views.generic import ListView, UpdateView 
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from django.shortcuts import get_object_or_404, render, redirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 
from rest_framework.views import APIView   

from apps.accounts.models import Useraccess
from apps.channels.models import Channels, ChannelsZone 
from apps.playlists.models import Playlists, Windows, Avails, AdspotsInAvail
from apps.playlists.utils import PlaylistXMLGenerator


class PlaylistView(LoginRequiredMixin, View):
    """
    Class-based view for handling playlist creation and management.
    Supports both regular playlist creation and draft playlist creation.
    """
    
    def get(self, request):
        """
        Handle GET requests - render the playlist creation page.
        
        Returns:
            Rendered template with available channels for the user.
        """
        user = request.user
        channels = Channels.objects.filter(id_user=user)
        
        context = {
            'data': {
                'channels': channels
            }
        }
        
        return render(request, "playlists/new.html", context)
    
    def post(self, request):
        """
        Handle POST requests - create playlist based on submitted data.
        
        Returns:
            Redirect to appropriate page based on action (apply/draft).
        """
        user = request.user
        
        # Determine which button was pressed
        apply_btn = request.POST.get("apply_btn")
        draft_btn = request.POST.get("draft_btn")
        
        if apply_btn: 
            return self._handle_apply_playlist(request, user)
        elif draft_btn: 
            return self._handle_draft_playlist(request, user)
        
        
        messages.error(
            request, 
            "Invalid submission. Please use either 'Save as Draft' or 'Submit Playlist' button."
        )
        return redirect("playlists:list_playlist")
    
    def _extract_common_data(self, request):
        """
        Extract common data from POST request.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            dict: Dictionary containing extracted data
        """
        channel_id = request.POST.get('channel_id')
        channel = Channels.objects.get(id_channel=channel_id)
        
        zonename = request.POST.get('zonename', '').strip()
        channel_zone = ChannelsZone.objects.get(
            id_channel=channel_id, 
            id_zone_channel=zonename
        )
        
        number_of_windows = request.POST.get('numofwin')
        
        # Parse and format date
        daydate = request.POST.get('day')
        daydate = datetime.datetime.strptime(str(daydate), '%m/%d/%Y')
        daydate = daydate.strftime('%Y-%m-%d')
        
        return {
            'channel_id': channel_id,
            'channel': channel,
            'channel_zone': channel_zone,
            'number_of_windows': number_of_windows,
            'daydate': daydate
        }
    
    def _handle_apply_playlist(self, request, user):
        """
        Handle playlist application (non-draft).
        
        Args:
            request: Django HTTP request object
            user: Current user object
            
        Returns:
            Redirect to playlist view page
        """
        data = self._extract_common_data(request)
        draft_version = request.POST.get('draft_version')
        
        # Create main playlist record
        playlist = Playlists(
            channel_id=data['channel_id'],
            version=1,
            broadcast_date=data['daydate'],
            start_date=f"{data['daydate']}T00:01:00+00:00",
            end_date=f"{data['daydate']}T23:59:00+00:00", 
            zone_channel_id=data['channel_zone'].id_zone_channel,
            is_draft=False,
            draft_version=0
        )
        playlist.save()
        
        # Process windows, avails, and ads
        traffic_counter = self._process_playlist_structure(
            request, playlist, data['daydate'], data['number_of_windows']
        )
        
        # Generate XML schedule
        generator = PlaylistXMLGenerator()
        xml_playlist_res = generator.generate_schedule(playlist)
        
        # Commented FTP upload logic preserved for reference
        # self._handle_ftp_upload(xml_playlist_res, playlist)
        
        # Commented activity logging preserved for reference
        # self._log_activity(playlist)
        
        return redirect("playlists:playlist_detail", id_playlist=playlist.id)
    
    def _handle_draft_playlist(self, request, user):
        """
        Handle draft playlist creation.
        
        Args:
            request: Django HTTP request object
            user: Current user object
            
        Returns:
            Redirect to draft playlist page
        """
        data = self._extract_common_data(request)
        
        # Create draft playlist record
        playlist = Playlists(
            channel_id=data['channel_id'],
            version=1,
            broadcast_date=str(data['daydate']),
            start_date=f"{data['daydate']}T00:01:00+00:00",  # Fixed missing variables
            end_date=f"{data['daydate']}T23:59:00+00:00",    # Fixed missing variables 
            zone_channel_id=data['channel_zone'].id_zone_channel,
            is_draft=True,
            draft_version=1
        )
        playlist.save()
        
        # Process windows, avails, and ads
        traffic_counter = self._process_playlist_structure(
            request, playlist, data['daydate'], data['number_of_windows']
        )
        
        # Commented XML generation and FTP upload preserved for reference
        # self._handle_draft_xml_generation(data, playlist)
        
        return redirect("playlists:draft_playlist", id_playlist=playlist.id)
    
    def _process_playlist_structure(self, request, playlist, daydate, number_of_windows):
        """
        Process the nested structure of windows, avails, and ads.
        
        Args:
            request: Django HTTP request object
            playlist: Playlist model instance
            daydate: Formatted date string
            number_of_windows: Number of windows to process
            
        Returns:
            int: Traffic counter value
        """
        traffic = 0
        
        if not number_of_windows or int(number_of_windows) <= 0:
            return traffic
        
        for i in range(int(number_of_windows)):
            numofavails = request.POST.get(f'numofavails[{i}]')
            
            if not numofavails:
                continue
                
            # Process window data
            window_start = request.POST.get(f'windowstart[{i}]')
            window_start = f"{daydate} {window_start}:00"
            
            window_end = request.POST.get(f'windowend[{i}]')
            window_end = f"{daydate} {window_end}:00"
            
            # Calculate window duration
            window_duration = self._calculate_window_duration(window_start, window_end)
            
            # Create window record
            window = Windows(
                playlist=playlist,
                window_start=datetime.datetime.strptime(window_start, '%Y-%m-%d %H:%M:%S').time(),
                window_end=datetime.datetime.strptime(window_end, '%Y-%m-%d %H:%M:%S').time(),
                window_duration=window_duration
            )
            window.save()
            
            # Process avails for this window
            traffic = self._process_avails(
                request, window, daydate, i, int(numofavails), traffic
            )
        
        return traffic
    
    def _process_avails(self, request, window, daydate, window_index, numofavails, traffic):
        """
        Process avails for a given window.
        
        Args:
            request: Django HTTP request object
            window: Window model instance
            daydate: Formatted date string
            window_index: Index of the current window
            numofavails: Number of avails to process
            traffic: Current traffic counter
            
        Returns:
            int: Updated traffic counter
        """
        for j in range(numofavails):
            avail_start_key = f'availstart[{window_index}][{j}]'
            av_start = request.POST.get(avail_start_key)
            
            if not av_start:
                continue
                
            av_start = f"{daydate} {av_start}:00"
            av_start = datetime.datetime.strptime(av_start, '%Y-%m-%d %H:%M:%S').time()
            number_of_ads = request.POST.get(f'numofads[{window_index}][{j}]')
            
            # Create avail record
            avail = Avails(
                window=window,
                avail_start=av_start,
                availinwindow=str(j + 1),
                datetime=datetime.datetime.now()
            )
            avail.save()
            
            # Process ads for this avail
            if number_of_ads:
                traffic = self._process_ads(
                    request, avail, window_index, j, int(number_of_ads), traffic
                )
        
        return traffic
    
    def _process_ads(self, request, avail, window_index, avail_index, number_of_ads, traffic):
        """
        Process ads for a given avail.
        
        Args:
            request: Django HTTP request object
            avail: Avail model instance
            window_index: Index of the current window
            avail_index: Index of the current avail
            number_of_ads: Number of ads to process
            traffic: Current traffic counter
            
        Returns:
            int: Updated traffic counter
        """
        for k in range(number_of_ads):
            ad_key = f'ad[{window_index}][{avail_index}][{k}]'
            adspot = request.POST.get(ad_key)
            
            if not adspot:
                continue
                
            traffic += 1
            
            # Create ad spot record
            ads_in_avail = AdspotsInAvail(
                avail=avail,
                adspot_id=adspot,
                positioninavail=str(k + 1),
                trafficid=traffic
            )
            ads_in_avail.save()
        
        return traffic
    
    def _calculate_window_duration(self, window_start, window_end):
        """
        Calculate window duration in the required format.
        
        Args:
            window_start: Window start datetime string
            window_end: Window end datetime string
            
        Returns:
            str: Formatted duration string
        """
        FMT = '%Y-%m-%d %H:%M:%S'
        
        start_dt = datetime.datetime.strptime(window_start, FMT)
        end_dt = datetime.datetime.strptime(window_end, FMT)
        
        duration = end_dt - start_dt
        duration_dt = datetime.datetime.strptime(str(duration), '%H:%M:%S')
        
        return duration_dt.strftime('%H%M%S00')
 
    def _handle_ftp_upload(self, xml_playlist_res, playlist):
        """
        Handle FTP upload of generated XML file.
        Currently commented out in original code.
        """
        pass
        # if xml_playlist_res["status"]:
        #     ftp_config = self._get_ftp_config(playlist)
        #     ftp = FTPConnector(**ftp_config)
        #     ftp.upload_file(xml_playlist_res["file"], ftp_config['remote_path'])
    
    def _log_activity(self, playlist):
        """
        Log playlist creation activity.
        Currently commented out in original code.
        """
        pass
        # activity = Activity(
        #     activity="Add PlayList",
        #     date=datetime.datetime.now(),
        #     description=f"Admin Add PlayList id: {playlist.id_playlist}"
        # )
        # activity.save()
    
    def _handle_draft_xml_generation(self, data, playlist):
        """
        Handle XML generation for draft playlist.
        Currently commented out in original code.
        """
        pass
        # xmlfilename = GenerateXMLfromDatabase(
        #     data['daydate'], 
        #     data['channel_id'], 
        #     data['channel_zone'].id_zone_channel, 
        #     '1'
        # )
        # Upload logic here...


class PlaylistListView(LoginRequiredMixin, View):
    """
    Class-based view for listing and filtering playlists using base View class.
    Supports search, filtering, sorting, and pagination with full control.
    """
    
    def get(self, request):
        """
        Handle GET requests for playlist listing.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            HttpResponse or JsonResponse for AJAX requests
        """
        # Check for AJAX requests
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return self._handle_ajax_request(request)
        
        # Get filtered queryset
        queryset = self._get_filtered_queryset(request)
        
        # Apply pagination
        paginator = Paginator(queryset, self._get_items_per_page(request))
        page_number = request.GET.get('page', 1)
        
        try:
            page_obj = paginator.get_page(page_number)
        except PageNotAnInteger:
            page_obj = paginator.get_page(1)
        except EmptyPage:
            page_obj = paginator.get_page(paginator.num_pages)
        
        # Build context
        context = self._build_context(request, page_obj, paginator)
        
        return render(request, 'playlists/list.html', context)
    
    def post(self, request):
        """
        Handle POST requests for bulk operations.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            JsonResponse with operation results
        """
        action = request.POST.get('action')
        playlist_ids = request.POST.getlist('playlist_ids')
        
        if not playlist_ids:
            return JsonResponse({
                'success': False,
                'message': 'No playlists selected.'
            })
        
        if action == 'bulk_delete':
            return self._handle_bulk_delete(request, playlist_ids)
        elif action == 'bulk_export':
            return self._handle_bulk_export(request, playlist_ids)
        elif action == 'bulk_status_change':
            return self._handle_bulk_status_change(request, playlist_ids)
        
        return JsonResponse({
            'success': False,
            'message': 'Invalid action.'
        })
    
    def _get_filtered_queryset(self, request):
        """
        Get filtered and sorted queryset based on request parameters.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            QuerySet: Filtered playlist queryset
        """
        user = request.user
        
        # Base queryset with optimizations
        queryset = Playlists.objects.select_related(
            'channel',
            'zone_channel'
        ).prefetch_related(
            'windows',
            'windows__avails',
            'windows__avails__adspots_in_avail'
        ).annotate(
            window_count=Count('windows', distinct=True),
            total_avails=Count('windows__avails', distinct=True),
            total_ads=Count('windows__avails__adspots_in_avail', distinct=True)
        ).filter(
            channel__id_user=user  # Also note: should be 'channel' not 'id_channel'
        )
        
        # Apply filters
        queryset = self._apply_search_filter(request, queryset)
        queryset = self._apply_channel_filter(request, queryset)
        queryset = self._apply_date_filter(request, queryset)
        queryset = self._apply_status_filter(request, queryset)
        queryset = self._apply_zone_filter(request, queryset)
        
        # Apply sorting
        queryset = self._apply_sorting(request, queryset)
        
        return queryset
    
    def _apply_search_filter(self, request, queryset):
        """
        Apply search filter based on search query.
        
        Args:
            request: Django HTTP request object
            queryset: Base queryset
            
        Returns:
            QuerySet: Filtered queryset
        """
        search_query = request.GET.get('search', '').strip()
        
        if search_query:
            queryset = queryset.filter(
                Q(id_channel__channel_name__icontains=search_query) |
                Q(id_zone_channel__networkname__icontains=search_query) |
                Q(id_zone_channel__region__icontains=search_query) |
                Q(broadcast_date__icontains=search_query) |
                Q(version__icontains=search_query)
            )
        
        return queryset
    
    def _apply_channel_filter(self, request, queryset):
        """
        Apply channel filter.
        
        Args:
            request: Django HTTP request object
            queryset: Base queryset
            
        Returns:
            QuerySet: Filtered queryset
        """
        channel_id = request.GET.get('channel')
        
        if channel_id and channel_id != 'all':
            try:
                channel_id = int(channel_id)
                queryset = queryset.filter(id_channel_id=channel_id)
            except (ValueError, TypeError):
                pass
        
        return queryset
    
    def _apply_date_filter(self, request, queryset):
        """
        Apply date range filter with predefined and custom ranges.
        
        Args:
            request: Django HTTP request object
            queryset: Base queryset
            
        Returns:
            QuerySet: Filtered queryset
        """
        date_from = request.GET.get('date_from')
        date_to = request.GET.get('date_to')
        date_range = request.GET.get('date_range')
        
        # Handle predefined date ranges
        if date_range:
            today = timezone.now().date()
            
            if date_range == 'today':
                queryset = queryset.filter(broadcast_date=today)
            elif date_range == 'yesterday':
                yesterday = today - datetime.timedelta(days=1)
                queryset = queryset.filter(broadcast_date=yesterday)
            elif date_range == 'this_week':
                week_start = today - datetime.timedelta(days=today.weekday())
                queryset = queryset.filter(broadcast_date__gte=week_start)
            elif date_range == 'last_week':
                week_start = today - datetime.timedelta(days=today.weekday() + 7)
                week_end = week_start + datetime.timedelta(days=6)
                queryset = queryset.filter(
                    broadcast_date__gte=week_start,
                    broadcast_date__lte=week_end
                )
            elif date_range == 'this_month':
                month_start = today.replace(day=1)
                queryset = queryset.filter(broadcast_date__gte=month_start)
            elif date_range == 'last_month':
                if today.month == 1:
                    last_month = today.replace(year=today.year - 1, month=12, day=1)
                else:
                    last_month = today.replace(month=today.month - 1, day=1)
                
                # Calculate last day of previous month
                if last_month.month == 12:
                    month_end = last_month.replace(year=last_month.year + 1, month=1, day=1) - datetime.timedelta(days=1)
                else:
                    month_end = last_month.replace(month=last_month.month + 1, day=1) - datetime.timedelta(days=1)
                
                queryset = queryset.filter(
                    broadcast_date__gte=last_month,
                    broadcast_date__lte=month_end
                )
        
        # Handle custom date range
        if date_from:
            try:
                date_from_parsed = datetime.datetime.strptime(date_from, '%Y-%m-%d').date()
                queryset = queryset.filter(broadcast_date__gte=date_from_parsed)
            except ValueError:
                pass
        
        if date_to:
            try:
                date_to_parsed = datetime.datetime.strptime(date_to, '%Y-%m-%d').date()
                queryset = queryset.filter(broadcast_date__lte=date_to_parsed)
            except ValueError:
                pass
        
        return queryset
    
    def _apply_status_filter(self, request, queryset):
        """
        Apply status filter (draft/published).
        
        Args:
            request: Django HTTP request object
            queryset: Base queryset
            
        Returns:
            QuerySet: Filtered queryset
        """
        status = request.GET.get('status')
        
        if status == 'draft':
            queryset = queryset.filter(is_draft='1')
        elif status == 'published':
            queryset = queryset.filter(is_draft='0')
        
        return queryset
    
    def _apply_zone_filter(self, request, queryset):
        """
        Apply zone/region filter.
        
        Args:
            request: Django HTTP request object
            queryset: Base queryset
            
        Returns:
            QuerySet: Filtered queryset
        """
        zone_id = request.GET.get('zone')
        
        if zone_id and zone_id != 'all':
            try:
                zone_id = int(zone_id)
                queryset = queryset.filter(id_zone_channel_id=zone_id)
            except (ValueError, TypeError):
                pass
        
        return queryset
    
    def _apply_sorting(self, request, queryset):
        """
        Apply sorting based on sort parameter.
        
        Args:
            request: Django HTTP request object
            queryset: Base queryset
            
        Returns:
            QuerySet: Sorted queryset
        """
        sort_by = request.GET.get('sort_by', '-created_at')
        
        valid_sort_fields = [
            'created_at', '-created_at',
            'broadcast_date', '-broadcast_date',
            'id_channel__channel_name', '-id_channel__channel_name',
            'version', '-version',
            'window_count', '-window_count',
            'total_ads', '-total_ads',
            'total_avails', '-total_avails',
            'is_draft', '-is_draft'
        ]
        
        if sort_by in valid_sort_fields:
            queryset = queryset.order_by(sort_by)
        else:
            # Default sorting
            queryset = queryset.order_by('-created_at')
        
        return queryset
    
    def _get_items_per_page(self, request):
        """
        Get number of items per page from request or default.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            int: Items per page
        """
        try:
            per_page = int(request.GET.get('per_page', 20))
            # Limit to reasonable range
            return max(10, min(per_page, 100))
        except (ValueError, TypeError):
            return 20
    
    def _build_context(self, request, page_obj, paginator):
        """
        Build template context with all necessary data.
        
        Args:
            request: Django HTTP request object
            page_obj: Paginated page object
            paginator: Paginator instance
            
        Returns:
            dict: Template context
        """
        user = request.user
        
        context = {
            # Pagination data
            'playlists': page_obj.object_list,
            'page_obj': page_obj,
            'paginator': paginator,
            'is_paginated': paginator.num_pages > 1,
            
            # Filter data
            'channels': self._get_user_channels(user),
            'zones': self._get_available_zones(user),
            'filter_params': self._get_current_filters(request),
            'sort_options': self._get_sort_options(),
            
            # Statistics
            'stats': self._get_playlist_stats(user),
            
            # Additional data
            'date_range': self._get_date_range(),
            'total_results': paginator.count,
            'current_page': page_obj.number,
            'total_pages': paginator.num_pages,
        }
        
        return context
    
    def _get_user_channels(self, user):
        """
        Get channels available to the current user.
        
        Args:
            user: Current user object
            
        Returns:
            QuerySet: User's channels
        """
        return Channels.objects.filter(id_user=user).order_by('channel_name')
    
    def _get_available_zones(self, user):
        """
        Get zones available to the current user.
        
        Args:
            user: Current user object
            
        Returns:
            QuerySet: Available zones
        """
        return ChannelsZone.objects.filter(
            id_channel__id_user=user
        ).distinct().order_by('networkname', 'region')
    
    def _get_current_filters(self, request):
        """
        Get current filter parameters for template.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            dict: Current filter values
        """
        return {
            'search': request.GET.get('search', ''),
            'channel': request.GET.get('channel', 'all'),
            'zone': request.GET.get('zone', 'all'),
            'status': request.GET.get('status', 'all'),
            'date_from': request.GET.get('date_from', ''),
            'date_to': request.GET.get('date_to', ''),
            'date_range': request.GET.get('date_range', ''),
            'sort_by': request.GET.get('sort_by', '-created_at'),
            'per_page': request.GET.get('per_page', '20'),
        }
    
    def _get_sort_options(self):
        """
        Get available sorting options.
        
        Returns:
            list: Sort options for template
        """
        return [
            {'value': '-created_at', 'label': 'Newest First'},
            {'value': 'created_at', 'label': 'Oldest First'},
            {'value': '-broadcast_date', 'label': 'Broadcast Date (Newest)'},
            {'value': 'broadcast_date', 'label': 'Broadcast Date (Oldest)'},
            {'value': 'id_channel__channel_name', 'label': 'Channel Name (A-Z)'},
            {'value': '-id_channel__channel_name', 'label': 'Channel Name (Z-A)'},
            {'value': '-window_count', 'label': 'Most Windows'},
            {'value': '-total_ads', 'label': 'Most Ads'},
            {'value': '-total_avails', 'label': 'Most Avails'},
            {'value': 'is_draft', 'label': 'Published First'},
            {'value': '-is_draft', 'label': 'Drafts First'},
        ]
        
        
    def _get_playlist_stats(self, user):
        """
            Get playlist statistics for dashboard.

            Args:
            user: Current user object

            Returns:
            dict: Playlist statistics
        """

        base_queryset = Playlists.objects.filter(channel__id_user=user)
        today = timezone.now().date()
        week_ago = today - datetime.timedelta(days=7)

        return {
            'total_playlists': base_queryset.count(),
            'draft_playlists': base_queryset.filter(is_draft='1').count(),
            'published_playlists': base_queryset.filter(is_draft='0').count(),
            'todays_playlists': base_queryset.filter(broadcast_date=today).count(),
            'recent_playlists': base_queryset.filter(
                created_at__gte=timezone.now() - datetime.timedelta(days=7)
            ).count(),
            'upcoming_playlists': base_queryset.filter(
                broadcast_date__gt=today,
                is_draft='0'
            ).count(),
            'past_playlists': base_queryset.filter(
                broadcast_date__lt=today
            ).count(),
        } 

    def _get_date_range(self):
        """
        Get date range information for filtering.
        
        Returns:
            dict: Date range options
        """
        today = timezone.now().date()
        
        return {
            'today': today,
            'yesterday': today - datetime.timedelta(days=1),
            'week_start': today - datetime.timedelta(days=today.weekday()),
            'month_start': today.replace(day=1),
            'min_date': today - datetime.timedelta(days=365),  # One year ago
            'max_date': today + datetime.timedelta(days=365),  # One year ahead
        }
    
    def _handle_ajax_request(self, request):
        """
        Handle AJAX requests for dynamic updates.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            JsonResponse: JSON response with data
        """
        action = request.GET.get('action')
        
        if action == 'get_zones':
            return self._get_zones_for_channel_ajax(request)
        elif action == 'quick_stats':
            return self._get_quick_stats_ajax(request)
        elif action == 'export_data':
            return self._export_playlist_data_ajax(request)
        elif action == 'load_more':
            return self._load_more_playlists_ajax(request)
        
        # Default: return filtered playlist data
        return self._get_filtered_playlists_ajax(request)
    
    def _get_zones_for_channel_ajax(self, request):
        """
        Get zones for a specific channel via AJAX.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            JsonResponse: JSON response with zone data
        """
        channel_id = request.GET.get('channel_id')
        
        if not channel_id:
            return JsonResponse({'success': False, 'error': 'Channel ID required'})
        
        try:
            channel_id = int(channel_id)
            zones = ChannelsZone.objects.filter(
                id_channel_id=channel_id
            ).values('id_zone_channel', 'networkname', 'region')
            
            return JsonResponse({
                'success': True,
                'zones': list(zones)
            })
        except (ValueError, TypeError):
            return JsonResponse({'success': False, 'error': 'Invalid channel ID'})
    
    def _get_quick_stats_ajax(self, request):
        """
        Get quick statistics via AJAX.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            JsonResponse: JSON response with statistics
        """
        user = request.user
        stats = self._get_playlist_stats(user)
        
        return JsonResponse({
            'success': True,
            'stats': stats
        })
    
    def _export_playlist_data_ajax(self, request):
        """
        Export playlist data via AJAX.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            JsonResponse: JSON response with export status
        """
        # Get filtered queryset for export
        queryset = self._get_filtered_queryset(request)
        
        # For now, return success with count
        # In a real implementation, you would generate a file and return the URL
        return JsonResponse({
            'success': True,
            'message': f'Export prepared for {queryset.count()} playlists',
            'download_url': '#',  # Replace with actual download URL
            'count': queryset.count()
        })
    
    def _load_more_playlists_ajax(self, request):
        """
        Load more playlists for infinite scroll.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            JsonResponse: JSON response with more playlists
        """
        page = request.GET.get('page', 1)
        per_page = self._get_items_per_page(request)
        
        queryset = self._get_filtered_queryset(request)
        paginator = Paginator(queryset, per_page)
        
        try:
            page_obj = paginator.get_page(page)
        except (PageNotAnInteger, EmptyPage):
            return JsonResponse({'success': False, 'error': 'Invalid page'})
        
        playlists_data = []
        for playlist in page_obj.object_list:
            playlists_data.append({
                'id': playlist.id_playlist,
                'channel_name': playlist.id_channel.channel_name,
                'zone': f"{playlist.id_zone_channel.networkname} - {playlist.id_zone_channel.region}",
                'broadcast_date': playlist.broadcast_date.strftime('%Y-%m-%d'),
                'version': playlist.version,
                'is_draft': playlist.is_draft == '1',
                'window_count': getattr(playlist, 'window_count', 0),
                'total_ads': getattr(playlist, 'total_ads', 0),
                'total_avails': getattr(playlist, 'total_avails', 0),
                'creation_date': playlist.created_at.strftime('%Y-%m-%d %H:%M'),
                'detail_url': f'/playlists/{playlist.id_playlist}/',
                'edit_url': f'/playlists/{playlist.id_playlist}/edit/',
            })
        
        return JsonResponse({
            'success': True,
            'playlists': playlists_data,
            'has_next': page_obj.has_next(),
            'next_page': page_obj.next_page_number() if page_obj.has_next() else None,
            'total_pages': paginator.num_pages,
            'current_page': page_obj.number
        })
    
    def _get_filtered_playlists_ajax(self, request):
        """
        Get filtered playlists for AJAX requests.
        
        Args:
            request: Django HTTP request object
            
        Returns:
            JsonResponse: JSON response with filtered playlists
        """
        queryset = self._get_filtered_queryset(request)
        
        # Limit results for AJAX to avoid large responses
        limit = min(int(request.GET.get('limit', 50)), 100)
        playlists = queryset[:limit]
        
        playlists_data = []
        for playlist in playlists:
            playlists_data.append({
                'id': playlist.id_playlist,
                'channel_name': playlist.id_channel.channel_name,
                'zone': f"{playlist.id_zone_channel.networkname} - {playlist.id_zone_channel.region}",
                'broadcast_date': playlist.broadcast_date.strftime('%Y-%m-%d'),
                'version': playlist.version,
                'is_draft': playlist.is_draft == '1',
                'window_count': getattr(playlist, 'window_count', 0),
                'total_ads': getattr(playlist, 'total_ads', 0),
                'creation_date': playlist.created_at.strftime('%Y-%m-%d %H:%M'),
            })
        
        return JsonResponse({
            'success': True,
            'playlists': playlists_data,
            'total_count': queryset.count(),
            'displayed_count': len(playlists_data)
        })
    
    def _handle_bulk_delete(self, request, playlist_ids):
        """
        Handle bulk deletion of playlists.
        
        Args:
            request: Django HTTP request object
            playlist_ids: List of playlist IDs to delete
            
        Returns:
            JsonResponse: Result of bulk operation
        """
        try:
            user = request.user
            deleted_count = 0
            errors = []
            
            for playlist_id in playlist_ids:
                try:
                    playlist = Playlists.objects.get(
                        id_playlist=playlist_id,
                        id_channel__id_user=user
                    )
                    
                    # Check if can delete (same logic as single delete)
                    today = datetime.date.today()
                    if playlist.broadcast_date >= today and playlist.is_draft == '0':
                        errors.append(f"Cannot delete active playlist {playlist_id}")
                        continue
                    
                    # Delete playlist and related objects
                    self._delete_playlist_cascade(playlist)
                    deleted_count += 1
                    
                except Playlists.DoesNotExist:
                    errors.append(f"Playlist {playlist_id} not found")
                except Exception as e:
                    errors.append(f"Error deleting playlist {playlist_id}: {str(e)}")
            
            return JsonResponse({
                'success': True,
                'deleted_count': deleted_count,
                'errors': errors,
                'message': f'Successfully deleted {deleted_count} playlists'
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'message': f'Bulk delete failed: {str(e)}'
            })
    
    def _handle_bulk_export(self, request, playlist_ids):
        """
        Handle bulk export of playlists.
        
        Args:
            request: Django HTTP request object
            playlist_ids: List of playlist IDs to export
            
        Returns:
            JsonResponse: Result of bulk operation
        """
        # Placeholder for bulk export functionality
        return JsonResponse({
            'success': True,
            'message': f'Export prepared for {len(playlist_ids)} playlists',
            'download_url': '#'  # Replace with actual export URL
        })
    
    def _handle_bulk_status_change(self, request, playlist_ids):
        """
        Handle bulk status change (draft/published).
        
        Args:
            request: Django HTTP request object
            playlist_ids: List of playlist IDs to update
            
        Returns:
            JsonResponse: Result of bulk operation
        """
        new_status = request.POST.get('new_status')
        
        if new_status not in ['0', '1']:  # 0 = published, 1 = draft
            return JsonResponse({
                'success': False,
                'message': 'Invalid status value'
            })
        
        try:
            user = request.user
            updated_count = 0
            
            playlists = Playlists.objects.filter(
                id_playlist__in=playlist_ids,
                id_channel__id_user=user
            )
            
            for playlist in playlists:
                playlist.is_draft = new_status
                playlist.save()
                updated_count += 1
            
            status_name = 'draft' if new_status == '1' else 'published'
            
            return JsonResponse({
                'success': True,
                'updated_count': updated_count,
                'message': f'Successfully updated {updated_count} playlists to {status_name}'
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'message': f'Bulk status update failed: {str(e)}'
            })
    
    def _delete_playlist_cascade(self, playlist):
        """
        Delete playlist and all related objects in proper order.
        
        Args:
            playlist: Playlist model instance
        """
        # Delete in reverse order of creation to maintain referential integrity
        for window in playlist.windows_set.all():
            for avail in window.avails_set.all():
                avail.adspotsinAvail_set.all().delete()
            window.avails_set.all().delete()
        playlist.windows_set.all().delete()
        playlist.delete()


class PlaylistDetailView(LoginRequiredMixin, View):
    """
    Detailed view for individual playlist with related data.
    """
    
    def get(self, request, id_playlist):
        """
        Display detailed playlist information.
        
        Args:
            request: Django HTTP request object
            id_playlist: Playlist ID
            
        Returns:
            HttpResponse: Rendered template
        """
        try:
            playlist = Playlists.objects.select_related(
                'id_channel',
                'id_zone_channel'
            ).prefetch_related(
                'windows_set__avails_set__adspotsinAvail_set__id_adspot'
            ).get(
                id_playlist=id_playlist,
                id_channel__id_user=request.user
            )
            
            context = {
                'playlist': playlist,
                'windows': self._get_playlist_windows(playlist),
                'stats': self._get_detailed_stats(playlist),
                'timeline': self._get_playlist_timeline(playlist),
            }
            
            return render(request, 'playlists/detail.html', context)
            
        except Playlists.DoesNotExist:
            return render(request, 'playlists/not_found.html', status=404)
    
    def _get_playlist_windows(self, playlist):
        """
        Get organized window data for the playlist.
        
        Args:
            playlist: Playlist model instance
            
        Returns:
            list: Organized window data
        """
        windows_data = []
        
        for window in playlist.windows_set.all().order_by('window_start'):
            avails_data = []
            
            for avail in window.avails_set.all().order_by('availinwindow'):
                ads_data = []
                
                for ad in avail.adspotsinAvail_set.all().order_by('positioninavail'):
                    ads_data.append({
                        'adspot': ad.id_adspot,
                        'position': ad.positioninavail,
                        'traffic_id': ad.trafficid,
                    })
                
                avails_data.append({
                    'avail': avail,
                    'ads': ads_data,
                })
            
            windows_data.append({
                'window': window,
                'avails': avails_data,
            })
        
        return windows_data
    
    def _get_detailed_stats(self, playlist):
        """
        Get detailed statistics for the playlist.
        
        Args:
            playlist: Playlist model instance
            
        Returns:
            dict: Detailed statistics
        """
        windows = playlist.windows_set.all()
        total_avails = sum(window.avails_set.count() for window in windows)
        total_ads = sum(
            avail.adspotsinAvail_set.count() 
            for window in windows 
            for avail in window.avails_set.all()
        )
        
        return {
            'total_windows': windows.count(),
            'total_avails': total_avails,
            'total_ads': total_ads,
            'avg_ads_per_avail': round(total_ads / total_avails, 2) if total_avails > 0 else 0,
            'duration_info': self._calculate_total_duration(windows),
        }
    
    def _calculate_total_duration(self, windows):
        """
        Calculate total duration information.
        
        Args:
            windows: Window queryset
            
        Returns:
            dict: Duration information
        """
        total_minutes = 0
        
        for window in windows:
            # Parse duration format (HHMMSS00)
            duration_str = window.window_duration
            if len(duration_str) >= 6:
                hours = int(duration_str[:2])
                minutes = int(duration_str[2:4])
                seconds = int(duration_str[4:6])
                total_minutes += (hours * 60) + minutes + (seconds / 60)
        
        return {
            'total_minutes': round(total_minutes, 2),
            'total_hours': round(total_minutes / 60, 2),
        }
    
    def _get_playlist_timeline(self, playlist):
        """
        Get timeline information for the playlist.
        
        Args:
            playlist: Playlist model instance
            
        Returns:
            list: Timeline events
        """
        timeline = [
            {
                'event': 'Playlist Created',
                'datetime': playlist.created_at,
                'type': 'creation',
                'description': f'Playlist version {playlist.version} created'
            }
        ]
        
        # Add window-based events
        for window in playlist.windows_set.all().order_by('window_start'):
            timeline.append({
                'event': 'Window Scheduled',
                'datetime': window.window_start,
                'type': 'window',
                'description': f'Window with {window.avails_set.count()} avails'
            })
        
        return sorted(timeline, key=lambda x: x['datetime'])


class PlaylistEditView(LoginRequiredMixin, View):
    """
    Class-based view for editing playlists with form handling.
    Combines the functionality of the original new_playlist view but for editing.
    """
    
    def get(self, request, playlist_id):
        """
        Handle GET requests - render the edit form with existing data.
        
        Args:
            request: Django HTTP request object
            playlist_id: ID of the playlist to edit
            
        Returns:
            Rendered edit form template
        """
        playlist = get_object_or_404(
            Playlists.objects.select_related('id_channel', 'id_zone_channel')
                             .prefetch_related('windows_set__avails_set__adspotsinAvail_set'),
            id_playlist=playlist_id,
            id_channel__id_user=request.user
        )
        
        # Check if playlist can be edited
        if not self._can_edit_playlist(playlist):
            messages.error(request, "This playlist cannot be edited.")
            return redirect('playlists:playlist_detail', id_playlist=playlist_id)
        
        # Get user channels for form
        channels = Channels.objects.filter(id_user=request.user)
        
        # Get zones for the current channel
        zones = ChannelsZone.objects.filter(id_channel=playlist.id_channel)
        
        # Structure existing data for the form
        playlist_data = self._structure_playlist_data(playlist)
        
        context = {
            'playlist': playlist,
            'playlist_data': playlist_data,
            'data': {'channels': channels},
            'zones': zones,
            'is_edit': True
        }
        
        return render(request, "playlists/edit.html", context)
    
    def post(self, request, playlist_id):
        """
        Handle POST requests - update the playlist.
        
        Args:
            request: Django HTTP request object
            playlist_id: ID of the playlist to edit
            
        Returns:
            Redirect to appropriate page
        """
        playlist = get_object_or_404(
            Playlists.objects.select_related('id_channel', 'id_zone_channel'),
            id_playlist=playlist_id,
            id_channel__id_user=request.user
        )
        
        # Check if playlist can be edited
        if not self._can_edit_playlist(playlist):
            messages.error(request, "This playlist cannot be edited.")
            return redirect('playlists:playlist_detail', id_playlist=playlist_id)
        
        # Determine action
        apply_btn = request.POST.get("apply_btn")
        draft_btn = request.POST.get("draft_btn")
        
        if apply_btn:
            return self._handle_update_playlist(request, playlist)
        elif draft_btn:
            return self._handle_save_as_draft(request, playlist)
        
        return redirect("playlists:edit_playlist", playlist_id=playlist_id)
    
    def _can_edit_playlist(self, playlist):
        """
        Check if playlist can be edited.
        
        Args:
            playlist: Playlist model instance
            
        Returns:
            bool: True if playlist can be edited
        """
        # Can edit if it's a draft or if broadcast date is in the future
        today = datetime.date.today()
        
        if playlist.is_draft == '1':
            return True
        
        if playlist.broadcast_date > today:
            return True
        
        return False
    
    def _structure_playlist_data(self, playlist):
        """
        Structure existing playlist data for form rendering.
        
        Args:
            playlist: Playlist model instance
            
        Returns:
            dict: Structured playlist data
        """
        data = {
            'windows': [],
            'channel_id': playlist.id_channel.id_channel,
            'zone_id': playlist.id_zone_channel.id_zone_channel,
            'broadcast_date': playlist.broadcast_date.strftime('%m/%d/%Y'),
            'version': playlist.version,
            'is_draft': playlist.is_draft == '1'
        }
        
        for window in playlist.windows_set.all().order_by('id_window'):
            window_data = {
                'id': window.id_window,
                'start_time': window.window_start.strftime('%H:%M'),
                'end_time': window.window_end.strftime('%H:%M'),
                'avails': []
            }
            
            for avail in window.avails_set.all().order_by('availinwindow'):
                avail_data = {
                    'id': avail.id_avail,
                    'start_time': avail.avail_start.strftime('%H:%M'),
                    'position': avail.availinwindow,
                    'ads': []
                }
                
                for ad in avail.adspotsinAvail_set.all().order_by('positioninavail'):
                    avail_data['ads'].append({
                        'id': ad.id_adspotsinAvail,
                        'adspot_id': ad.id_adspot.id_adspot,
                        'position': ad.positioninavail,
                        'traffic_id': ad.trafficid
                    })
                
                window_data['avails'].append(avail_data)
            
            data['windows'].append(window_data)
        
        return data
    
    def _handle_update_playlist(self, request, playlist):
        """
        Handle playlist update (apply changes).
        
        Args:
            request: Django HTTP request object
            playlist: Playlist model instance
            
        Returns:
            HttpResponse redirect
        """
        try:
            with transaction.atomic():
                # Update playlist basic info
                self._update_playlist_basic_info(request, playlist)
                
                # Clear existing structure
                self._clear_playlist_structure(playlist)
                
                # Recreate structure with new data
                self._recreate_playlist_structure(request, playlist)
                
                # Generate XML if needed
                xml_playlist_res = generateSchedule(playlist)
                
                # Log the update activity
                self._log_update_activity(request.user, playlist)
            
            messages.success(request, "Playlist updated successfully.")
            return redirect("playlists:playlist_detail", id_playlist=playlist.id_playlist)
            
        except Exception as e:
            messages.error(request, f"Error updating playlist: {str(e)}")
            return redirect("playlists:edit_playlist", playlist_id=playlist.id_playlist)
    
    def _handle_save_as_draft(self, request, playlist):
        """
        Handle saving playlist as draft.
        
        Args:
            request: Django HTTP request object
            playlist: Playlist model instance
            
        Returns:
            HttpResponse redirect
        """
        try:
            with transaction.atomic():
                # Update playlist to draft status
                playlist.is_draft = '1'
                playlist.draft_version = str(int(playlist.version) + 1)
                
                # Update basic info
                self._update_playlist_basic_info(request, playlist)
                
                # Clear and recreate structure
                self._clear_playlist_structure(playlist)
                self._recreate_playlist_structure(request, playlist)
                
                playlist.save()
                
                # Log the draft save activity
                self._log_draft_activity(request.user, playlist)
            
            messages.success(request, "Playlist saved as draft.")
            return redirect("playlists:draft_playlist")
            
        except Exception as e:
            messages.error(request, f"Error saving draft: {str(e)}")
            return redirect("playlists:edit_playlist", playlist_id=playlist.id_playlist)
    
    def _update_playlist_basic_info(self, request, playlist):
        """
        Update basic playlist information.
        
        Args:
            request: Django HTTP request object
            playlist: Playlist model instance
        """
        # Extract basic info from request
        daydate = request.POST.get('day')
        if daydate:
            daydate = datetime.datetime.strptime(str(daydate), '%m/%d/%Y')
            daydate = daydate.strftime('%Y-%m-%d')
            
            playlist.broadcast_date = daydate
            playlist.start_date = f"{daydate}T00:01:00+00:00"
            playlist.end_date = f"{daydate}T23:59:00+00:00"
        
        # Update zone if changed
        zonename = request.POST.get('zonename', '').strip()
        if zonename:
            channel_zone = ChannelsZone.objects.get(
                id_channel=playlist.id_channel,
                id_zone_channel=zonename
            )
            playlist.id_zone_channel = channel_zone
        
        playlist.save()
    
    def _clear_playlist_structure(self, playlist):
        """
        Clear existing playlist structure (windows, avails, ads).
        
        Args:
            playlist: Playlist model instance
        """
        # Delete in proper order to maintain referential integrity
        for window in playlist.windows_set.all():
            for avail in window.avails_set.all():
                avail.adspotsinAvail_set.all().delete()
            window.avails_set.all().delete()
        playlist.windows_set.all().delete()
    
    def _recreate_playlist_structure(self, request, playlist):
        """
        Recreate playlist structure from form data.
        Uses the same logic as the original new_playlist view.
        
        Args:
            request: Django HTTP request object
            playlist: Playlist model instance
        """
        number_of_windows = request.POST.get('numofwin')
        daydate = playlist.broadcast_date.strftime('%Y-%m-%d')
        traffic = 0
        
        if number_of_windows and int(number_of_windows) > 0:
            for i in range(int(number_of_windows)):
                if request.POST.get(f'numofavails[{i}]'):
                    numofavails = request.POST.get(f'numofavails[{i}]')
                    
                    # Create window
                    window_start = request.POST.get(f'windowstart[{i}]')
                    window_start = f"{daydate} {window_start}:00"
                    
                    window_end = request.POST.get(f'windowend[{i}]')
                    window_end = f"{daydate} {window_end}:00"
                    
                    # Calculate duration
                    FMT = '%Y-%m-%d %H:%M:%S'
                    window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                    window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                    window_duration = window_duration.strftime('%H%M%S00')
                    
                    window = Windows(
                        id_playlist=playlist,
                        window_start=window_start,
                        window_end=window_end,
                        window_duration=window_duration
                    )
                    window.save()
                    
                    # Create avails
                    for j in range(int(numofavails)):
                        if request.POST.get(f'availstart[{i}][{j}]'):
                            av_start = request.POST.get(f'availstart[{i}][{j}]')
                            av_start = f"{daydate} {av_start}:00"
                            
                            number_of_ads = request.POST.get(f'numofads[{i}][{j}]')
                            
                            avail = Avails(
                                id_window=window,
                                avail_start=av_start,
                                availinwindow=str(j + 1),
                                datetime=datetime.datetime.now()
                            )
                            avail.save()
                            
                            # Create ads
                            for k in range(int(number_of_ads)):
                                if request.POST.get(f'ad[{i}][{j}][{k}]'):
                                    adspot = request.POST.get(f'ad[{i}][{j}][{k}]')
                                    traffic += 1
                                    
                                    ads_in_avail = AdspotsInAvail(
                                        id_avail=avail,
                                        id_adspot_id=adspot,
                                        positioninavail=str(k + 1),
                                        trafficid=traffic
                                    )
                                    ads_in_avail.save()
    
    def _log_update_activity(self, user, playlist):
        """
        Log playlist update activity.
        
        Args:
            user: User who updated the playlist
            playlist: Updated playlist instance
        """
        try:
            activity = Activity(
                activity="Update Playlist",
                date=datetime.datetime.now(),
                description=f"User {user.username} updated playlist ID: {playlist.id_playlist} "
                           f"for channel {playlist.id_channel.channel_name}"
            )
            activity.save()
        except:
            pass
    
    def _log_draft_activity(self, user, playlist):
        """
        Log playlist draft save activity.
        
        Args:
            user: User who saved the draft
            playlist: Draft playlist instance
        """
        try:
            activity = Activity(
                activity="Save Playlist Draft",
                date=datetime.datetime.now(),
                description=f"User {user.username} saved playlist ID: {playlist.id_playlist} as draft"
            )
            activity.save()
        except:
            pass


class PlaylistDeleteView(LoginRequiredMixin, View):
    """
    Class-based view for deleting playlists with proper authorization.
    Supports both AJAX and regular HTTP requests.
    """
    
    def post(self, request, playlist_id):
        """
        Handle playlist deletion.
        
        Args:
            request: Django HTTP request object
            playlist_id: ID of the playlist to delete
            
        Returns:
            JsonResponse or HttpResponse redirect
        """
        try:
            playlist = get_object_or_404(
                Playlists.objects.select_related('id_channel'),
                id_playlist=playlist_id,
                id_channel__id_user=request.user
            )
            
            # Check if playlist can be deleted
            if not self._can_delete_playlist(playlist):
                return self._handle_delete_error(
                    request, 
                    "Cannot delete this playlist. It may be currently active or have dependencies."
                )
            
            # Store playlist info for logging
            playlist_info = {
                'id': playlist.id_playlist,
                'channel': playlist.id_channel.channel_name,
                'broadcast_date': playlist.broadcast_date,
                'version': playlist.version
            }
            
            # Delete playlist and related objects
            with transaction.atomic():
                self._delete_playlist_cascade(playlist)
            
            # Log the deletion activity
            self._log_deletion_activity(request.user, playlist_info)
            
            # Handle AJAX vs regular request
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': f'Playlist for {playlist_info["channel"]} deleted successfully.'
                })
            else:
                messages.success(
                    request, 
                    f'Playlist for {playlist_info["channel"]} deleted successfully.'
                )
                return redirect('playlists:list_playlist')
                
        except Playlists.DoesNotExist:
            return self._handle_delete_error(request, "Playlist not found.")
        except Exception as e:
            return self._handle_delete_error(request, f"Error deleting playlist: {str(e)}")
    
    def get(self, request, playlist_id):
        """
        Handle GET request - show confirmation page.
        
        Args:
            request: Django HTTP request object
            playlist_id: ID of the playlist to delete
            
        Returns:
            Rendered confirmation template
        """
        playlist = get_object_or_404(
            Playlists.objects.select_related('id_channel', 'id_zone_channel'),
            id_playlist=playlist_id,
            id_channel__id_user=request.user
        )
        
        context = {
            'playlist': playlist,
            'dependencies': self._get_playlist_dependencies(playlist),
            'can_delete': self._can_delete_playlist(playlist)
        }
        
        return render(request, 'playlists/confirm_delete.html', context)
    
    def _can_delete_playlist(self, playlist):
        """
        Check if playlist can be safely deleted.
        
        Args:
            playlist: Playlist model instance
            
        Returns:
            bool: True if playlist can be deleted
        """
        # Check if playlist is currently active (broadcast date is today or future)
        today = datetime.date.today()
        if playlist.broadcast_date >= today and playlist.is_draft == '0':
            return False
        
        # Add other business rules here
        # e.g., check if playlist is referenced by other systems
        
        return True
    
    def _delete_playlist_cascade(self, playlist):
        """
        Delete playlist and all related objects in proper order.
        
        Args:
            playlist: Playlist model instance
        """
        # Delete in reverse order of creation to maintain referential integrity
        
        # Delete ad spots in avails
        for window in playlist.windows_set.all():
            for avail in window.avails_set.all():
                avail.adspotsinAvail_set.all().delete()
        
        # Delete avails
        for window in playlist.windows_set.all():
            window.avails_set.all().delete()
        
        # Delete windows
        playlist.windows_set.all().delete()
        
        # Delete the playlist itself
        playlist.delete()
    
    def _get_playlist_dependencies(self, playlist):
        """
        Get information about playlist dependencies.
        
        Args:
            playlist: Playlist model instance
            
        Returns:
            dict: Dependencies information
        """
        dependencies = {
            'windows': playlist.windows_set.count(),
            'total_avails': 0,
            'total_ads': 0
        }
        
        for window in playlist.windows_set.all():
            avails_count = window.avails_set.count()
            dependencies['total_avails'] += avails_count
            
            for avail in window.avails_set.all():
                dependencies['total_ads'] += avail.adspotsinAvail_set.count()
        
        return dependencies
    
    def _log_deletion_activity(self, user, playlist_info):
        """
        Log playlist deletion activity.
        
        Args:
            user: User who deleted the playlist
            playlist_info: Dictionary with playlist information
        """
        try:
            activity = Activity(
                activity="Delete Playlist",
                date=datetime.datetime.now(),
                description=f"User {user.username} deleted playlist ID: {playlist_info['id']} "
                           f"for channel {playlist_info['channel']} "
                           f"(Broadcast: {playlist_info['broadcast_date']})"
            )
            activity.save()
        except:
            # Log activity is optional, don't fail if it doesn't work
            pass
    
    def _handle_delete_error(self, request, error_message):
        """
        Handle deletion errors for both AJAX and regular requests.
        
        Args:
            request: Django HTTP request object
            error_message: Error message string
            
        Returns:
            JsonResponse or HttpResponse redirect
        """
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'message': error_message
            })
        else:
            messages.error(request, error_message)
            return redirect('playlists:list_playlist')


class PlaylistDuplicateView(LoginRequiredMixin, View):
    """
    Class-based view for duplicating playlists with all related objects.
    """
    
    def post(self, request, playlist_id):
        """
        Handle playlist duplication.
        
        Args:
            request: Django HTTP request object
            playlist_id: ID of the playlist to duplicate
            
        Returns:
            JsonResponse or HttpResponse redirect
        """
        try:
            original_playlist = get_object_or_404(
                Playlists.objects.select_related('id_channel', 'id_zone_channel'),
                id_playlist=playlist_id,
                id_channel__id_user=request.user
            )
            
            # Get duplication parameters
            new_broadcast_date = request.POST.get('broadcast_date')
            copy_as_draft = request.POST.get('as_draft', 'false').lower() == 'true'
            
            # Validate new broadcast date
            if new_broadcast_date:
                try:
                    new_date = datetime.datetime.strptime(new_broadcast_date, '%Y-%m-%d').date()
                except ValueError:
                    return self._handle_duplicate_error(request, "Invalid broadcast date format.")
            else:
                # Default to tomorrow
                new_date = datetime.date.today() + datetime.timedelta(days=1)
            
            # Check for existing playlist on the same date
            if self._playlist_exists_for_date(original_playlist, new_date):
                return self._handle_duplicate_error(
                    request, 
                    f"A playlist already exists for {new_date} on this channel."
                )
            
            # Duplicate the playlist
            with transaction.atomic():
                new_playlist = self._duplicate_playlist_structure(
                    original_playlist, 
                    new_date, 
                    copy_as_draft
                )
            
            # Log the duplication activity
            self._log_duplication_activity(request.user, original_playlist, new_playlist)
            
            # Handle AJAX vs regular request
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': f'Playlist duplicated successfully for {new_date}.',
                    'new_playlist_id': new_playlist.id_playlist,
                    'redirect_url': reverse('playlists:playlist_detail', args=[new_playlist.id_playlist])
                })
            else:
                messages.success(
                    request, 
                    f'Playlist duplicated successfully for {new_date}.'
                )
                return redirect('playlists:playlist_detail', id_playlist=new_playlist.id_playlist)
                
        except Playlists.DoesNotExist:
            return self._handle_duplicate_error(request, "Original playlist not found.")
        except Exception as e:
            return self._handle_duplicate_error(request, f"Error duplicating playlist: {str(e)}")
    
    def get(self, request, playlist_id):
        """
        Show duplication form.
        
        Args:
            request: Django HTTP request object
            playlist_id: ID of the playlist to duplicate
            
        Returns:
            Rendered duplication form template
        """
        playlist = get_object_or_404(
            Playlists.objects.select_related('id_channel', 'id_zone_channel'),
            id_playlist=playlist_id,
            id_channel__id_user=request.user
        )
        
        # Get suggested dates (next 7 days, excluding existing playlists)
        suggested_dates = self._get_suggested_dates(playlist)
        
        context = {
            'playlist': playlist,
            'suggested_dates': suggested_dates,
            'default_date': datetime.date.today() + datetime.timedelta(days=1)
        }
        
        return render(request, 'playlists/duplicate_form.html', context)
    
    def _playlist_exists_for_date(self, original_playlist, target_date):
        """
        Check if a playlist already exists for the target date.
        
        Args:
            original_playlist: Original playlist instance
            target_date: Target broadcast date
            
        Returns:
            bool: True if playlist exists for the date
        """
        return Playlists.objects.filter(
            id_channel=original_playlist.id_channel,
            id_zone_channel=original_playlist.id_zone_channel,
            broadcast_date=target_date
        ).exists()
    
    def _duplicate_playlist_structure(self, original_playlist, new_date, as_draft):
        """
        Duplicate the entire playlist structure.
        
        Args:
            original_playlist: Original playlist instance
            new_date: New broadcast date
            as_draft: Whether to create as draft
            
        Returns:
            Playlists: New playlist instance
        """
        # Create new playlist
        new_playlist = Playlists(
            id_channel=original_playlist.id_channel,
            version="1",  # Always start with version 1 for duplicates
            broadcast_date=new_date,
            start_date=f"{new_date}T00:01:00+00:00",
            end_date=f"{new_date}T23:59:00+00:00", 
            id_zone_channel=original_playlist.id_zone_channel,
            is_draft='1' if as_draft else '0',
            draft_version='1' if as_draft else '0'
        )
        new_playlist.save()
        
        # Duplicate windows and related structures
        traffic_counter = 0
        
        for original_window in original_playlist.windows_set.all().order_by('id_window'):
            # Calculate new window times for the new date
            new_window_start, new_window_end = self._calculate_new_window_times(
                original_window, new_date
            )
            
            # Create new window
            new_window = Windows(
                id_playlist=new_playlist,
                window_start=new_window_start,
                window_end=new_window_end,
                window_duration=original_window.window_duration
            )
            new_window.save()
            
            # Duplicate avails
            for original_avail in original_window.avails_set.all().order_by('id_avail'):
                new_avail_start = self._calculate_new_avail_start(original_avail, new_date)
                
                new_avail = Avails(
                    id_window=new_window,
                    avail_start=new_avail_start,
                    availinwindow=original_avail.availinwindow,
                    datetime=datetime.datetime.now()
                )
                new_avail.save()
                
                # Duplicate ads
                for original_ad in original_avail.adspotsinAvail_set.all().order_by('id_adspotsinAvail'):
                    traffic_counter += 1
                    
                    new_ad = AdspotsInAvail(
                        id_avail=new_avail,
                        id_adspot=original_ad.id_adspot,
                        positioninavail=original_ad.positioninavail,
                        trafficid=traffic_counter
                    )
                    new_ad.save()
        
        return new_playlist
    
    def _calculate_new_window_times(self, original_window, new_date):
        """
        Calculate new window start and end times for the new date.
        
        Args:
            original_window: Original window instance
            new_date: New broadcast date
            
        Returns:
            tuple: (new_start_time, new_end_time)
        """
        # Extract time from original window
        original_start = original_window.window_start
        original_end = original_window.window_end
        
        # Create new datetime with new date but same time
        new_start = datetime.datetime.combine(
            new_date, 
            original_start.time()
        )
        new_end = datetime.datetime.combine(
            new_date, 
            original_end.time()
        )
        
        return new_start.strftime('%Y-%m-%d %H:%M:%S'), new_end.strftime('%Y-%m-%d %H:%M:%S')
    
    def _calculate_new_avail_start(self, original_avail, new_date):
        """
        Calculate new avail start time for the new date.
        
        Args:
            original_avail: Original avail instance
            new_date: New broadcast date
            
        Returns:
            str: New avail start time
        """
        original_start = original_avail.avail_start
        new_start = datetime.datetime.combine(
            new_date, 
            original_start.time()
        )
        return new_start.strftime('%Y-%m-%d %H:%M:%S')
    
    def _get_suggested_dates(self, playlist):
        """
        Get suggested dates for duplication (next 7 days without existing playlists).
        
        Args:
            playlist: Original playlist instance
            
        Returns:
            list: List of suggested dates
        """
        suggested_dates = []
        current_date = datetime.date.today() + datetime.timedelta(days=1)
        
        for i in range(14):  # Check next 14 days
            if not self._playlist_exists_for_date(playlist, current_date):
                suggested_dates.append(current_date)
                
            current_date += datetime.timedelta(days=1)
            
            # Stop after finding 7 available dates
            if len(suggested_dates) >= 7:
                break
        
        return suggested_dates
    
    def _log_duplication_activity(self, user, original_playlist, new_playlist):
        """
        Log playlist duplication activity.
        
        Args:
            user: User who duplicated the playlist
            original_playlist: Original playlist instance
            new_playlist: New playlist instance
        """
        try:
            activity = Activity(
                activity="Duplicate Playlist",
                date=datetime.datetime.now(),
                description=f"User {user.username} duplicated playlist ID: {original_playlist.id_playlist} "
                           f"to new playlist ID: {new_playlist.id_playlist} "
                           f"(New broadcast date: {new_playlist.broadcast_date})"
            )
            activity.save()
        except:
            # Log activity is optional, don't fail if it doesn't work
            pass
    
    def _handle_duplicate_error(self, request, error_message):
        """
        Handle duplication errors for both AJAX and regular requests.
        
        Args:
            request: Django HTTP request object
            error_message: Error message string
            
        Returns:
            JsonResponse or HttpResponse redirect
        """
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'message': error_message
            })
        else:
            messages.error(request, error_message)
            return redirect('playlists:list_playlist')



@require_http_methods(["GET", "POST"])
@login_required
@csrf_protect
def new_playlist(request):
    # 
    user = request.user
    # 
    if request.method == 'GET':
        # Render the form  
        channels = Channels.objects.filter(id_user=user)
        return render(request, "playlists/new.html",{'data': {'channels': channels}})  
    # 
    elif request.method == 'POST':
        # 
        apply_btn = request.POST.get("apply_btn")
        # 
        draft_btn = request.POST.get("draft_btn")
        #
        useraccess = Useraccess.objects.filter(id_user=user)
        #  
        channel_id = request.POST.get('channel_id')
        channel = Channels.objects.get(id_channel=channel_id)
        # 
        zonename = request.POST.get('zonename', '').strip() 
        channel_zone = ChannelsZone.objects.get(id_channel=channel_id, id_zone_channel=zonename)
        # 
        number_of_windows = request.POST.get('numofwin')
        # 
        daydate = request.POST.get('day')  
        daydate = datetime.datetime.strptime(str(daydate), '%m/%d/%Y')
        daydate = daydate.strftime('%Y-%m-%d')
        # 
        if(apply_btn): 
            #
            draft_version = request.POST.get('draft_version') 
            #
            Playlist = Playlists(
                id_channel_id      = channel_id ,
                version            = "1",
                broadcast_date      = f"{daydate}",
                start_date         = f"{daydate}T00:01:00+00:00",
                end_date           = f"{daydate}T23:59:00+00:00", 
                id_zone_channel_id = channel_zone.id_zone_channel,
                is_draft           = '0',
                draft_version      = '0'
            )
            Playlist.save()
            #
            traffic = 0
            record_inserted = 0
            #
            if number_of_windows and (int(number_of_windows) > 0):
                #
                for i in range(int(number_of_windows)):
                    if request.POST.get('numofavails['+str(i)+']'):
                        #
                        numofavails = request.POST.get('numofavails['+str(i)+']')
                        #
                        window_start = request.POST.get('windowstart['+str(i)+']')
                        window_start = daydate+' '+window_start+':00'
                        window_end = request.POST.get('windowend['+str(i)+']')
                        window_end = daydate+' '+window_end+':00'
                        #
                        FMT = '%Y-%m-%d %H:%M:%S'
                        #
                        window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                        window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                        window_duration = window_duration.strftime('%H%M%S00')
                        #
                        Window = Windows(
                            id_playlist_id=Playlist.id_playlist,
                            window_start=window_start,
                            window_end=window_end,
                            window_duration=window_duration
                        )
                        Window.save()

                        for j in range(int(numofavails)):
                            if request.POST.get('availstart['+str(i)+']['+str(j)+']'):
                                #
                                av_start = request.POST.get('availstart['+str(i)+']['+str(j)+']')
                                av_start = daydate+' '+av_start+':00'
                                #
                                number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                                #
                                Avail = Avails(
                                    id_window_id  = Window.id_window,
                                    avail_start   = av_start,
                                    availinwindow = str(j+1),
                                    datetime      = datetime.datetime.now(),
                                )
                                Avail.save()

                                for k in range(int(number_of_ads)):
                                    if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                                        #
                                        adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                                        #
                                        traffic +=1
                                        #
                                        AdspotsInAv = AdspotsInAvail(
                                            id_avail_id     = Avail.id_avail,
                                            id_adspot_id    = adspot,
                                            positioninavail = str(k+1),
                                            trafficid       = traffic
                                        )
                                        AdspotsInAv.save()

                xml_playlist_res = generateSchedule(Playlist)

                # # Check the result
                # if xml_playlist_res["status"]:
                #     ftp_host = "172.16.205.1"
                #     ftp_port =  60000
                #     ftp_username = "SanoaMedia"
                #     ftp_password = "SanoaMedia"
                #     local_file_path = xml_playlist_res["file"]
                #     remote_file_path = "2M/schedules/REG1_NL"

                #     if Playlist.id_zone_channel.networkname == "REGNL":
                #         remote_file_path = "2M/schedules/REG1_NL"
                #     elif Playlist.id_zone_channel.networkname == "2M":
                #         remote_file_path = "2M/schedules/REG1_FR"
                #     # uploadFTP(ftp_server, ftp_port, ftp_user, ftp_password, xml_file_path , ftp_upload_path)
                #     ftp = FTPConnector(ftp_host, ftp_port, ftp_username, ftp_password)
                #     # Upload a file to the server
                #     ftp.upload_file(local_file_path, remote_file_path)
                # else:
                #     print(f"Failed to generate playlist file. Error: {xml_playlist_res['message']}")

                # activity = Activity(
                #     activity    = "Add PlayList",
                #     date        = datetime.datetime.now(),
                #     description = f"Admin Add PlayList  id: { Playlist.id_playlist }"
                # )
                # activity.save()

                ############ Display data on playlist_detail_id page ##################
                return redirect("playlists:playlist_detail", id_playlist = Playlist.id)
            #
            return redirect("playlists:new_playlist")
        elif(draft_btn):    
            Playlist = Playlists(
                id_channel_id=channel_id,
                version="1", 
                broadcast_date=str(daydate), 
                start_date=start_date, 
                end_date=end_date,  
                id_zone_channel_id=channel_zone.id_zone_channel,
                is_draft='1',
                draft_version='1'
            )
            Playlist.save()
            
            traffic = 0
            record_inserted = 0

            for i in range(int(number_of_windows)):
                if request.POST.get('numofavails['+str(i)+']'):
                    numofavails = request.POST.get('numofavails['+str(i)+']')
                    window_start = request.POST.get('windowstart['+str(i)+']')
                    window_start = daydate+' '+window_start+':00'
                    window_end = request.POST.get('windowend['+str(i)+']')
                    window_end = daydate+' '+window_end+':00'
                    FMT = '%Y-%m-%d %H:%M:%S'
                    window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                    window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                    window_duration = window_duration.strftime('%H%M%S00')
                    Window = Windows(id_playlist_id=Playlist.id_playlist, window_start=window_start, window_end=window_end, window_duration=window_duration )
                    Window.save()

                    for j in range(int(numofavails)):
                        if request.POST.get('availstart['+str(i)+']['+str(j)+']'):
                            av_start = request.POST.get('availstart['+str(i)+']['+str(j)+']')
                            av_start = daydate+' '+av_start+':00'
                            number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                            Avail = Avails(id_window_id=Window.id_window, avail_start=av_start, availinwindow=str(j+1), datetime=now )
                            Avail.save()

                            for k in range(int(number_of_ads)):
                                if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                                    adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                                    traffic +=1
                                    AdspotsInAv = AdspotsInAvail(id_avail_id=Avail.id_avail, id_adspot_id=adspot, positioninavail=str(k+1), trafficid=traffic)
                                    AdspotsInAv.save()
            
            # xmlfilename = GenerateXMLfromDatabase(daydate, channel_id, channel_zone.id_zone_channel, '1' )
            # path_inftp = channeldata.ftp_channel_name+'/schedules/'+channel_zone.region
            # uploadFTP(useraccess.ftp_server, useraccess.ftp_port, useraccess.ftp_user, useraccess.ftp_password, xmlfilename , path_inftp)
            
            last_id_playlist = Playlist.id_playlist

            ############ Display data on playlist_detail_id page ##################
            return redirect("playlists:draft_playlist") 


@login_required
def view_playlist(request, id_playlist):
    playlist = Playlists.objects.get(pk=id_playlist)
    channels = Channels.objects.filter(id_user=user)
    region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
    d = playlist.broadcast_date

    win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

    data = {}
    data["windows"] = []
    data["number_of_wins"] = 0
    i = 0
    record_inserted = 0
    windows = Windows.objects.filter(id_playlist=playlist.id_playlist)
    for window in windows:
        window_dic = {}
        window_dic['i'] = i
        i = i+1
        window_dic['id_window'] = window.id_window
        window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
        window_start_formated_2 = window_start_formated.strftime("%H:%M")
        window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
        window_end_formated_2 = window_end_formated.strftime("%H:%M")
        window_dic['window_start'] = window_start_formated_2
        window_dic['window_end'] = window_end_formated_2
        window_dic['avails_in_win'] = []
        window_dic['num_of_avails'] = 0
        data["number_of_wins"] = i
        avails = Avails.objects.filter(id_window=window.id_window)
        j = 0
        for avail in avails:
            avail_dic = {}
            avail_dic["j"] = j
            j = j+1
            avail_dic["id_avail"] = avail.id_avail

            avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
            avail_start_formated2 = avail_start_formated.strftime("%H:%M")

            avail_dic["avail_start"] = avail_start_formated2
            avail_dic["adspots_in_avail"] = []
            window_dic["avails_in_win"].append(avail_dic)
            adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
            window_dic['num_of_avails'] = j
            k = 0
            avail_dic["num_of_adspots"] = 0
            for adspot in adspots:
                adspot_dic = {}
                adspot_dic["k"] = k
                k = k+1
                avail_dic["num_of_adspots"] = k
                adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                adspot_dic["id_adspot"] = adspot.id_adspot
                avail_dic["adspots_in_avail"].append(adspot_dic)
        data["windows"].append(window_dic)
        record_inserted = 0


    data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"],'record_inserted':record_inserted}
    return render(request, "core/view_playlist_id.html", data_playlist)


@login_required
def edit_playlist(request,id_playlist="1"):
    if request.method == 'POST':
        edit_btn = request.POST.get("edit_btn")
        view_btn = request.POST.get("view_btn")
        insertion_results_btn = request.POST.get("insertion_results_btn")
        duplicate_btn = request.POST.get("duplicate_btn")
        draft_btn = request.POST.get("draft_btn")
        if(edit_btn):
            playlist = Playlists.objects.get(pk=id_playlist)
            channels = Channels.objects.filter(id_user=user)
            region = ChannelsZone.objects.get(
                id_zone_channel=playlist.id_zone_channel.id_zone_channel,
                region=playlist.id_zone_channel.region,
                zonename=playlist.id_zone_channel.zonename,
                networkname=playlist.id_zone_channel.networkname
            )
            # region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
            d = playlist.broadcast_date

            win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

            data = {}
            data["windows"] = []
            data["number_of_wins"] = 0
            i = 0

            windows = Windows.objects.filter(id_playlist=playlist.id_playlist).order_by('window_start')
            for window in windows:
                window_dic = {}
                window_dic['i'] = i
                i = i+1
                window_dic['id_window'] = window.id_window
                window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
                window_start_formated_2 = window_start_formated.strftime("%H:%M")
                window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
                window_end_formated_2 = window_end_formated.strftime("%H:%M")
                window_dic['window_start'] = window_start_formated_2
                window_dic['window_end'] = window_end_formated_2
                window_dic['avails_in_win'] = []
                window_dic['num_of_avails'] = 0
                data["number_of_wins"] = i
                avails = Avails.objects.filter(id_window=window.id_window)
                j = 0
                for avail in avails:
                    avail_dic = {}
                    avail_dic["j"] = j
                    j = j+1
                    avail_dic["id_avail"] = avail.id_avail
                    avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                    avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                    avail_dic["avail_start"] = avail_start_formated2
                    avail_dic["adspots_in_avail"] = []
                    window_dic["avails_in_win"].append(avail_dic)
                    adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                    window_dic['num_of_avails'] = j
                    k = 0
                    avail_dic["num_of_adspots"] = 0
                    for adspot in adspots:
                        adspot_dic = {}
                        adspot_dic["k"] = k
                        k = k+1
                        avail_dic["num_of_adspots"] = k
                        adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                        adspot_dic["id_adspot"] = adspot.id_adspot
                        avail_dic["adspots_in_avail"].append(adspot_dic)
                data["windows"].append(window_dic)


            now = datetime.datetime.now()
            activite = 'Edit PlayList'
            desc = 'Admin Edit PlayList  id: ' + str(playlist.id_playlist)
            activity = Activity(activity=activite , date=now ,description=desc )
            activity.save()

            data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
            return render(request, "core/edit_playlist_id.html", data_playlist)
        elif(duplicate_btn):
            playlist = Playlists.objects.get(pk=id_playlist)
            channels = Channels.objects.filter(id_user=user)
            region = ChannelsZone.objects.get(
                id_zone_channel=playlist.id_zone_channel.id_zone_channel,
                region=playlist.id_zone_channel.region,
                zonename=playlist.id_zone_channel.zonename,
                networkname=playlist.id_zone_channel.networkname
            )
            d = playlist.broadcast_date

            win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

            data = {}
            data["windows"] = []
            data["number_of_wins"] = 0
            i = 0

            windows = Windows.objects.filter(id_playlist=playlist.id_playlist)
            for window in windows:
                window_dic = {}
                window_dic['i'] = i
                i = i+1
                window_dic['id_window'] = window.id_window
                window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
                window_start_formated_2 = window_start_formated.strftime("%H:%M")
                window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
                window_end_formated_2 = window_end_formated.strftime("%H:%M")
                window_dic['window_start'] = window_start_formated_2
                window_dic['window_end'] = window_end_formated_2
                window_dic['avails_in_win'] = []
                window_dic['num_of_avails'] = 0
                data["number_of_wins"] = i
                avails = Avails.objects.filter(id_window=window.id_window)
                j = 0
                for avail in avails:
                    avail_dic = {}
                    avail_dic["j"] = j
                    j = j+1
                    avail_dic["id_avail"] = avail.id_avail
                    avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                    avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                    avail_dic["avail_start"] = avail_start_formated2
                    avail_dic["adspots_in_avail"] = []
                    window_dic["avails_in_win"].append(avail_dic)
                    adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                    window_dic['num_of_avails'] = j
                    k = 0
                    avail_dic["num_of_adspots"] = 0
                    for adspot in adspots:
                        adspot_dic = {}
                        adspot_dic["k"] = k
                        k = k+1
                        avail_dic["num_of_adspots"] = k
                        adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                        adspot_dic["id_adspot"] = adspot.id_adspot
                        avail_dic["adspots_in_avail"].append(adspot_dic)
                data["windows"].append(window_dic)


            data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
            return render(request, "core/duplicate_playlist_id.html", data_playlist)
        elif(view_btn):
            return redirect("playlists:view_playlist", id_playlist=id_playlist)
        else:
            return redirect("playlists:insertion_results", id_playlist=id_playlist)
    else:
        now = datetime.datetime.now() - timedelta(days=30)
        id_session = str(user)
        channels = Channels.objects.filter(id_user=id_session).values_list('id_channel', flat=True)
        playlists = Playlists.objects.filter(id_channel__in=channels,is_draft='0',start_date__gte=now).order_by('-broadcast_date')
        windows= Windows.objects.filter(id_playlist__in=playlists)
        details = []
        for window in windows :
            detail = {}
            detail["id_playlist"]=window.id_playlist.id_playlist
            broadcast_date_verif = str(window.window_start).split(' ')[0]
            broadcast_date_verif = broadcast_date_verif.replace('-','')
            detail["window_start"] = str(window.window_start).split(' ')[1]
            detail["window_end"] = str(window.window_end).split(' ')[1]
            avails = Avails.objects.filter(id_window=window)
            detail["avails"] = []
            # for avail in avails:
            #     av = {}
            #     av['start']= str(avail.avail_start).split(' ')[1]
            #     AdspotsInAv = AdspotsInAvail.objects.filter(id_avail=avail)
            #     for adspot in AdspotsInAv:
            #         av["adspot"] = AdspotsInAvail.objects.filter(id_avail=avail)
            #         try:
            #             result = Verifs.objects.filter(broadcast_date = broadcast_date_verif, trafficId = adspot.trafficid).latest('id_verif')
            #             av["adspotname"] = adspot.id_adspot.adspot_name
            #             av["airStatusCode"] = result.airStatuscode
            #             av["airTime"] = result.airTime
            #         except Verifs.DoesNotExist:
            #             print('oups')
            #         else:
            #             print("file not ready yet")
            #     detail["avails"].append(av)
            # details.append(detail)


        data = {'playlists': playlists , 'details':details}
        return render(request, "core/edit_playlist.html",data)


@login_required
def update_playlist(request, id_playlist):
    if request.method == 'POST':
        apply_btn = request.POST.get("apply_btn")
        draft_btn = request.POST.get("draft_btn")
        if(apply_btn):
            id_user = user
            useraccess = Useraccess.objects.get(id_user=id_user)
            channel_id = request.POST.get('channel_id')
            channeldata = Channels.objects.get(id_channel=channel_id)

            # zonename = request.POST.get('zonename')

            daydate = request.POST.get('day')
            number_of_windows = request.POST.get('numofwin')
            #return HttpResponse(number_of_windows)
            # channel_zone = ChannelsZone.objects.get(id_channel=channel_id, zonename=zonename)
            version = request.POST.get('version')
            draft_version_old = request.POST.get('draft_version')

            daydate = datetime.datetime.strptime(str(daydate), '%Y-%m-%d')
            daydate = daydate.strftime('%Y-%m-%d')
            start_date = str(daydate) + "T00:01:00+00:00"
            end_date = str(daydate) + "T23:59:00+00:00"
            now = datetime.datetime.now()

            draft_version = request.POST.get('draft_version')

            playlist = Playlists.objects.get(pk=id_playlist)

            version_p = playlist.version
            broadcast_date_p = playlist.broadcast_date
            draft_version_p = playlist.draft_version
            start_date_p = playlist.start_date
            end_date_p = playlist.end_date

            # max_version = Playlists.objects.filter(broadcast_date=str(daydate)).aggregate(Max('version')).get('version__max')

            max_version = Playlists.objects.filter(
                broadcast_date = f"{daydate}",
                id_zone_channel = playlist.id_zone_channel.id_zone_channel
            ).count()

            new_version = int(max_version)+1

            Playlist = Playlists(
                id_channel_id      = channel_id ,
                version            = str(new_version),
                broadcast_date      = str(daydate),
                start_date         = start_date,
                end_date           = end_date, 
                # id_zone_channel_id = channel_zone.id_zone_channel,
                id_zone_channel_id = playlist.id_zone_channel.id_zone_channel,
                is_draft           = '0',
                draft_version      = draft_version_old
            )

            Playlist.save()
            traffic = 0
            record_inserted = 0
            var_test = 0
            for i in range(int(number_of_windows)):
                if request.POST.get('numofavails['+str(i)+']'):
                    numofavails = request.POST.get('numofavails['+str(i)+']')
                    window_start = request.POST.get('windowstart['+str(i)+']')
                    window_start = daydate+' '+window_start+':00'
                    window_end = request.POST.get('winend_['+str(i)+']')
                    window_end = daydate+' '+window_end+':00'
                    FMT = '%Y-%m-%d %H:%M:%S'
                    window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                    window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                    window_duration = window_duration.strftime('%H%M%S00')
                    Window = Windows(
                        id_playlist_id  = Playlist.id_playlist,
                        window_start    = window_start,
                        window_end      = window_end,
                        window_duration = window_duration
                    )
                    Window.save()

                    for j in range(int(numofavails)):
                        if request.POST.get('availstart['+str(i)+']['+str(j)+']'):
                            av_start = request.POST.get('availstart['+str(i)+']['+str(j)+']')
                            av_start = daydate+' '+av_start+':00'
                            number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                            Avail = Avails(
                                id_window_id  = Window.id_window,
                                avail_start   = av_start,
                                availinwindow = str(j+1),
                                datetime      = now
                            )
                            Avail.save()
                            for k in range(int(number_of_ads)):
                                if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                                    adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                                    traffic +=1
                                    AdspotsInAv = AdspotsInAvail(
                                        id_avail_id = Avail.id_avail,
                                        id_adspot_id = adspot,
                                        positioninavail = str(k+1),
                                        trafficid = traffic
                                    )
                                    AdspotsInAv.save()
                                    record_inserted = 1

            last_id_playlist = Playlist.id_playlist

            # xmlfilename = GenerateXMLfromDatabase(daydate, channel_id, channel_zone.id_zone_channel, str(new_version),draft_version_old)
            # path_inftp = channeldata.ftp_channel_name+'/schedules/'+channel_zone.region
            # uploadFTP(useraccess.ftp_server, useraccess.ftp_port, useraccess.ftp_user, useraccess.ftp_password, xmlfilename , path_inftp)

            xml_playlist_res = generateSchedule(Playlist)
            print(xml_playlist_res)
            # Check the result
            if xml_playlist_res["status"]:
                ftp_host = "172.16.205.1"
                ftp_port =  60000
                ftp_username = "SanoaMedia"
                ftp_password = "SanoaMedia"
                local_file_path = xml_playlist_res["file"]
                remote_file_path = None
                if Playlist.id_zone_channel.networkname == "REGNL":
                    remote_file_path = "2M/schedules/REG1_NL"
                elif Playlist.id_zone_channel.networkname == "2M":
                    remote_file_path = "2M/schedules/REG1_FR"
                if remote_file_path:
                    # uploadFTP(ftp_server, ftp_port, ftp_user, ftp_password, xml_file_path , ftp_upload_path)
                    ftp = FTPConnector(ftp_host, ftp_port, ftp_username, ftp_password)
                    # Upload a file to the server
                    ftp.upload_file(local_file_path, remote_file_path)
            else:
                print(f"Failed to generate playlist file. Error: {xml_playlist_res['message']}")

            activity = Activity(
                activity    = "Update PlayList",
                date        = datetime.datetime.now(),
                description = f"Admin Update PlayList id: { Playlist.id_playlist }"
            )
            activity.save()

            ############ Display data on view_playlist_id page ##################
            return redirect("playlists:playlist_detail", id_playlist=last_id_playlist)
        else:
                        useraccess = Useraccess.objects.get(id_user=user)
                        channel_id = request.POST.get('channel_id')
                        channeldata = Channels.objects.get(id_channel=channel_id)
                        zonename = request.POST.get('zonename')
                        daydate = request.POST.get('day')
                        number_of_windows = request.POST.get('numofwin')
                        channel_zone = ChannelsZone.objects.get(id_channel=channel_id, zonename=zonename)
                        playlist = Playlists.objects.get(pk=id_playlist)

                        version_p = playlist.version
                        broadcast_date_p = playlist.broadcast_date
                        draft_version_p = playlist.draft_version
                        start_date_p = playlist.start_date
                        end_date_p = playlist.end_date

                        max_version_draft = Playlists.objects.filter(broadcast_date=broadcast_date_p).aggregate(Max('draft_version')).get('draft_version__max')
                        new_version_draft = max_version_draft

                        #daydate = datetime.datetime.strptime(str(daydate), '%m/%d/%Y')
                        #daydate = daydate.strftime('%Y-%m-%d')
                        start_date = str(daydate) + "T00:01:00+00:00"
                        end_date = str(daydate) + "T23:59:00+00:00"
                        now = datetime.datetime.now()
                        Playlist = Playlists(
                            id_channel_id=channel_id,
                            version=version_p, 
                            broadcast_date=broadcast_date_p, 
                            start_date=start_date_p, 
                            end_date=end_date_p,  
                            id_zone_channel_id=channel_zone.id_zone_channel,
                            is_draft='1',
                            draft_version=new_version_draft+1
                        )
                        Playlist.save()
                        traffic = 0
                        record_inserted = 0
                        for i in range(int(number_of_windows)):
                            if request.POST.get('numofavails['+str(i)+']'):
                                numofavails = request.POST.get('numofavails['+str(i)+']')
                                window_start = request.POST.get('windowstart['+str(i)+']')
                                window_start = daydate+' '+window_start+':00'
                                window_end = request.POST.get('winend_['+str(i)+']')
                                window_end = daydate+' '+window_end+':00'
                                FMT = '%Y-%m-%d %H:%M:%S'
                                window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                                window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                                window_duration = window_duration.strftime('%H%M%S00')
                                Window = Windows(id_playlist_id=Playlist.id_playlist, window_start=window_start, window_end=window_end, window_duration=window_duration )
                                Window.save()

                                for j in range(int(numofavails)):
                                    if request.POST.get('availstart['+str(i)+']['+str(j)+']'):
                                        av_start = request.POST.get('availstart['+str(i)+']['+str(j)+']')
                                        av_start = daydate+' '+av_start+':00'
                                        number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                                        Avail = Avails(id_window_id=Window.id_window, avail_start=av_start, availinwindow=str(j+1), datetime=now )
                                        Avail.save()

                                        for k in range(int(number_of_ads)):
                                            if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                                                adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                                                traffic +=1
                                                AdspotsInAv = AdspotsInAvail(id_avail_id=Avail.id_avail, id_adspot_id=adspot, positioninavail=str(k+1), trafficid=traffic)
                                                AdspotsInAv.save()
                        # xmlfilename = GenerateXMLfromDatabase(daydate, channel_id, channel_zone.id_zone_channel, '1' )
                        # path_inftp = channeldata.ftp_channel_name+'/schedules/'+channel_zone.region
                        # uploadFTP(useraccess.ftp_server, useraccess.ftp_port, useraccess.ftp_user, useraccess.ftp_password, xmlfilename , path_inftp)
                        last_id_playlist = Playlist.id_playlist

                        ############ Display data on view_playlist_id page ##################
                        return redirect("playlist:draft_playlist")


@login_required
def duplicate_playlist(request,id_playlist="1"):
    if request.method == 'POST':
        playlist = Playlists.objects.get(pk=id_playlist)
        channels = Channels.objects.filter(id_user=user)
        region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
        d = playlist.broadcast_date

        win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

        data = {}
        data["windows"] = []
        data["number_of_wins"] = 0
        i = 0

        windows = Windows.objects.filter(id_playlist=playlist.id_playlist)
        for window in windows:
            window_dic = {}
            window_dic['i'] = i
            i = i+1
            window_dic['id_window'] = window.id_window
            window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
            window_start_formated_2 = window_start_formated.strftime("%H:%M")
            window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
            window_end_formated_2 = window_end_formated.strftime("%H:%M")
            window_dic['window_start'] = window_start_formated_2
            window_dic['window_end'] = window_end_formated_2
            window_dic['avails_in_win'] = []
            window_dic['num_of_avails'] = 0
            data["number_of_wins"] = i
            avails = Avails.objects.filter(id_window=window.id_window)
            j = 0
            for avail in avails:
                avail_dic = {}
                avail_dic["j"] = j
                j = j+1
                avail_dic["id_avail"] = avail.id_avail
                avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                avail_dic["avail_start"] = avail_start_formated2
                avail_dic["adspots_in_avail"] = []
                window_dic["avails_in_win"].append(avail_dic)
                adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                window_dic['num_of_avails'] = j
                k = 0
                avail_dic["num_of_adspots"] = 0
                for adspot in adspots:
                    adspot_dic = {}
                    adspot_dic["k"] = k
                    k = k+1
                    avail_dic["num_of_adspots"] = k
                    adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                    adspot_dic["id_adspot"] = adspot.id_adspot
                    avail_dic["adspots_in_avail"].append(adspot_dic)
            data["windows"].append(window_dic)


        data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
        return render(request, "core/duplicate_playlist_id.html", data_playlist)
    else:
        id_session = str(user)
        channels = Channels.objects.filter(id_user=id_session).values_list('id_channel', flat=True)
        playlists = Playlists.objects.filter(id_channel__in=channels).order_by('-id_playlist')
        data = {'playlists': playlists}
        return render(request, "core/duplicate_playlist.html",data)


@login_required
def duplicate_playlist_update(request, id_playlist):
    if request.method == 'POST':
        id_user = user
        useraccess = Useraccess.objects.get(id_user_id=id_user)
        channel_id = request.POST.get('channel_id')
        channeldata = Channels.objects.get(id_channel=channel_id)
        zonename = request.POST.get('zonename')
        daydate = request.POST.get('day')
        number_of_windows = request.POST.get('numofwin')
        #return HttpResponse(number_of_windows)
        channel_zone = ChannelsZone.objects.get(id_channel=channel_id, zonename=zonename)
        version = request.POST.get('version')

        daydate = datetime.datetime.strptime(str(daydate), '%m/%d/%Y')
        daydate = daydate.strftime('%Y-%m-%d')
        start_date = str(daydate) + "T00:01:00+00:00"
        end_date = str(daydate) + "T23:59:00+00:00"
        now = datetime.datetime.now()

        # max_version = Playlists.objects.filter(broadcast_date=str(daydate)).aggregate(Max('version')).get('version__max')
        filtered_playlists = Playlists.objects.filter(broadcast_date=str(daydate)).order_by('-created_at')
        last_playlist = filtered_playlists.first()
        last_playlist_version = int(last_playlist.version) if (last_playlist and hasattr(last_playlist, 'version') and last_playlist.version is not None) else 1

        Playlist = Playlists(
            id_channel_id=channel_id ,
            version=(last_playlist_version+1),
            broadcast_date=str(daydate),
            start_date=start_date,
            end_date=end_date, 
            id_zone_channel_id=channel_zone.id_zone_channel,
            is_draft='0',
            draft_version='0'
        )
        Playlist.save()
        traffic = 0
        record_inserted = 0
        var_test = 0
        for i in range(int(number_of_windows)):
            if request.POST.get('numofavails['+str(i)+']'):
                numofavails = request.POST.get('numofavails['+str(i)+']')
                window_start = request.POST.get('windowstart['+str(i)+']')
                window_start = daydate+' '+window_start+':00'
                window_end = request.POST.get('windowend['+str(i)+']')
                window_end = daydate+' '+window_end+':00'
                FMT = '%Y-%m-%d %H:%M:%S'
                window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                window_duration = window_duration.strftime('%H%M%S00')
                Window = Windows(id_playlist_id=Playlist.id_playlist, window_start=window_start, window_end=window_end, window_duration=window_duration )
                Window.save()

                for j in range(int(numofavails)):
                    if request.POST.get('availstart['+str(i)+']['+str(j)+']'):
                        av_start = request.POST.get('availstart['+str(i)+']['+str(j)+']')
                        av_start = daydate+' '+av_start+':00'
                        number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                        Avail = Avails(id_window_id=Window.id_window, avail_start=av_start, availinwindow=str(j+1), datetime=now )
                        Avail.save()

                        for k in range(int(number_of_ads)):
                            if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                                adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                                traffic +=1
                                AdspotsInAv = AdspotsInAvail(id_avail_id=Avail.id_avail, id_adspot_id=adspot, positioninavail=str(k+1), trafficid=traffic)
                                AdspotsInAv.save()
                                record_inserted = 1
        last_id_playlist = Playlist.id_playlist
        xmlfilename = GenerateXMLfromDatabase(daydate, channel_id, channel_zone.id_zone_channel, f"{(last_playlist_version+1)}")
        path_inftp = channeldata.ftp_channel_name+'/schedules/'+channel_zone.region
        # uploadFTP(useraccess.ftp_server, useraccess.ftp_port, useraccess.ftp_user, useraccess.ftp_password, xmlfilename , path_inftp)

        ############ Display data on view_playlist_id page ##################
        return redirect("playlists:view_playlist", id_playlist=last_id_playlist)


@login_required
def playlists_results(request,id_playlist="1"):
    if request.method == 'POST':
        edit_btn = request.POST.get("edit_btn")
        view_btn = request.POST.get("view_btn")
        insertion_results_btn = request.POST.get("insertion_results")
        duplicate_btn = request.POST.get("duplicate_btn")
        if(edit_btn):
            playlist = Playlists.objects.get(pk=id_playlist)
            channels = Channels.objects.filter(id_user=user)
            region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
            d = playlist.broadcast_date

            win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

            data = {}
            data["windows"] = []
            data["number_of_wins"] = 0
            i = 0

            windows = Windows.objects.filter(id_playlist=playlist.id_playlist).order_by('window_start')
            for window in windows:
                window_dic = {}
                window_dic['i'] = i
                i = i+1
                window_dic['id_window'] = window.id_window
                window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
                window_start_formated_2 = window_start_formated.strftime("%H:%M")
                window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
                window_end_formated_2 = window_end_formated.strftime("%H:%M")
                window_dic['window_start'] = window_start_formated_2
                window_dic['window_end'] = window_end_formated_2
                window_dic['avails_in_win'] = []
                window_dic['num_of_avails'] = 0
                data["number_of_wins"] = i
                avails = Avails.objects.filter(id_window=window.id_window)
                j = 0
                for avail in avails:
                    avail_dic = {}
                    avail_dic["j"] = j
                    j = j+1
                    avail_dic["id_avail"] = avail.id_avail
                    avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                    avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                    avail_dic["avail_start"] = avail_start_formated2
                    avail_dic["adspots_in_avail"] = []
                    window_dic["avails_in_win"].append(avail_dic)
                    adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                    window_dic['num_of_avails'] = j
                    k = 0
                    avail_dic["num_of_adspots"] = 0
                    for adspot in adspots:
                        adspot_dic = {}
                        adspot_dic["k"] = k
                        k = k+1
                        avail_dic["num_of_adspots"] = k
                        adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                        adspot_dic["id_adspot"] = adspot.id_adspot
                        avail_dic["adspots_in_avail"].append(adspot_dic)
                data["windows"].append(window_dic)


            data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
            return render(request, "core/edit_playlist_id.html", data_playlist)
        elif(duplicate_btn):
            playlist = Playlists.objects.get(pk=id_playlist)
            channels = Channels.objects.filter(id_user=user)
            region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
            d = playlist.broadcast_date

            win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

            data = {}
            data["windows"] = []
            data["number_of_wins"] = 0
            i = 0

            windows = Windows.objects.filter(id_playlist=playlist.id_playlist).order_by('window_start')
            for window in windows:
                window_dic = {}
                window_dic['i'] = i
                i = i+1
                window_dic['id_window'] = window.id_window
                window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
                window_start_formated_2 = window_start_formated.strftime("%H:%M")
                window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
                window_end_formated_2 = window_end_formated.strftime("%H:%M")
                window_dic['window_start'] = window_start_formated_2
                window_dic['window_end'] = window_end_formated_2
                window_dic['avails_in_win'] = []
                window_dic['num_of_avails'] = 0
                data["number_of_wins"] = i
                avails = Avails.objects.filter(id_window=window.id_window)
                j = 0
                for avail in avails:
                    avail_dic = {}
                    avail_dic["j"] = j
                    j = j+1
                    avail_dic["id_avail"] = avail.id_avail
                    avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                    avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                    avail_dic["avail_start"] = avail_start_formated2
                    avail_dic["adspots_in_avail"] = []
                    window_dic["avails_in_win"].append(avail_dic)
                    adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                    window_dic['num_of_avails'] = j
                    k = 0
                    avail_dic["num_of_adspots"] = 0
                    for adspot in adspots:
                        adspot_dic = {}
                        adspot_dic["k"] = k
                        k = k+1
                        avail_dic["num_of_adspots"] = k
                        adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                        adspot_dic["id_adspot"] = adspot.id_adspot
                        avail_dic["adspots_in_avail"].append(adspot_dic)
                data["windows"].append(window_dic)


            data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
            return render(request, "core/duplicate_playlist_id.html", data_playlist)
        elif(view_btn):
            return redirect("playlists:view_playlist", id_playlist=id_playlist)
        else:
            return redirect("playlists:insertion_results", id_playlist=id_playlist)
    else:
        id_session = str(user)
        channels = Channels.objects.filter(id_user=id_session).values_list('id_channel', flat=True)
        playlists = Playlists.objects.filter(id_channel__in=channels).order_by('-id_playlist')
        data = {'playlists': playlists}
        return render(request, "core/playlists_results.html",data)


@login_required
def draft_playlist(request,id_playlist="1"):
    if request.method == 'POST':
        playlist = Playlists.objects.get(pk=id_playlist)
        channels = Channels.objects.filter(id_user=user)
        region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
        d = playlist.broadcast_date

        win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

        data = {}
        data["windows"] = []
        data["number_of_wins"] = 0
        i = 0

        windows = Windows.objects.filter(id_playlist=playlist.id_playlist)
        for window in windows:
            window_dic = {}
            window_dic['i'] = i
            i = i+1
            window_dic['id_window'] = window.id_window
            window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
            window_start_formated_2 = window_start_formated.strftime("%H:%M")
            window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
            window_end_formated_2 = window_end_formated.strftime("%H:%M")
            window_dic['window_start'] = window_start_formated_2
            window_dic['window_end'] = window_end_formated_2
            window_dic['avails_in_win'] = []
            window_dic['num_of_avails'] = 0
            data["number_of_wins"] = i
            avails = Avails.objects.filter(id_window=window.id_window)
            j = 0
            for avail in avails:
                avail_dic = {}
                avail_dic["j"] = j
                j = j+1
                avail_dic["id_avail"] = avail.id_avail
                avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                avail_dic["avail_start"] = avail_start_formated2
                avail_dic["adspots_in_avail"] = []
                window_dic["avails_in_win"].append(avail_dic)
                adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                window_dic['num_of_avails'] = j
                k = 0
                avail_dic["num_of_adspots"] = 0
                for adspot in adspots:
                    adspot_dic = {}
                    adspot_dic["k"] = k
                    k = k+1
                    avail_dic["num_of_adspots"] = k
                    adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                    adspot_dic["id_adspot"] = adspot.id_adspot
                    avail_dic["adspots_in_avail"].append(adspot_dic)
            data["windows"].append(window_dic)

        data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
        return render(request, "core/edit_draft_playlist_id.html", data_playlist)
    else:
        id_session = str(user)
        channels = Channels.objects.filter(id_user=id_session).values_list('id_channel', flat=True)
        playlists = Playlists.objects.filter(id_channel__in=channels,is_draft='1').order_by('-id_playlist')
        data = {'playlists': playlists}
        return render(request, "core/draft_playlist.html",data)


@login_required
def update_draft_playlist(request, id_playlist):
    if request.method == 'POST':
        apply_btn = request.POST.get("apply_btn")
        draft_btn = request.POST.get("draft_btn")
        if(apply_btn):
            id_user = user
            useraccess = Useraccess.objects.get(id_user=id_user)
            channel_id = request.POST.get('channel_id')
            channeldata = Channels.objects.get(id_channel=channel_id)
            zonename = request.POST.get('zonename')
            daydate = request.POST.get('day')
            number_of_windows = request.POST.get('numofwin')
            #return HttpResponse(number_of_windows)
            channel_zone = ChannelsZone.objects.get(id_channel=channel_id, zonename=zonename)
            version = request.POST.get('version')

            daydate = datetime.datetime.strptime(str(daydate), '%Y-%m-%d')
            daydate = daydate.strftime('%Y-%m-%d')
            start_date = str(daydate) + "T00:01:00+00:00"
            end_date = str(daydate) + "T23:59:00+00:00"
            now = datetime.datetime.now()

            max_version = Playlists.objects.filter(broadcast_date=str(daydate)).aggregate(Max('version')).get('version__max')
            new_version = int(max_version)
            max_version_draft = Playlists.objects.filter(broadcast_date=str(daydate)).aggregate(Max('draft_version')).get('draft_version__max')
            new_version_draft = int(max_version_draft)
            Playlist = Playlists(
                id_channel_id=channel_id,
                version=int(max_version), 
                broadcast_date=str(daydate), 
                start_date=start_date, 
                end_date=end_date,  
                id_zone_channel_id=channel_zone.id_zone_channel,
                is_draft='0',
                draft_version=int(new_version_draft)
            )
            Playlist.save()
            traffic = 0
            record_inserted = 0
            var_test = 0
            for i in range(int(number_of_windows)):
                if request.POST.get('numofavails['+str(i)+']'):
                    numofavails = request.POST.get('numofavails['+str(i)+']')
                    window_start = request.POST.get('windowstart['+str(i)+']')
                    window_start = daydate+' '+window_start+':00'
                    window_end = request.POST.get('windowend['+str(i)+']')
                    window_end = daydate+' '+window_end+':00'
                    FMT = '%Y-%m-%d %H:%M:%S'
                    window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                    window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                    window_duration = window_duration.strftime('%H%M%S00')
                    Window = Windows(id_playlist_id=Playlist.id_playlist, window_start=window_start, window_end=window_end, window_duration=window_duration )
                    Window.save()

                    for j in range(int(numofavails)):
                        if request.POST.get('availstart['+str(i)+']['+str(j)+']'):
                            av_start = request.POST.get('availstart['+str(i)+']['+str(j)+']')
                            av_start = daydate+' '+av_start+':00'
                            number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                            Avail = Avails(id_window_id=Window.id_window, avail_start=av_start, availinwindow=str(j+1), datetime=now )
                            Avail.save()

                            for k in range(int(number_of_ads)):
                                if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                                    adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                                    traffic +=1
                                    AdspotsInAv = AdspotsInAvail(id_avail_id=Avail.id_avail, id_adspot_id=adspot, positioninavail=str(k+1), trafficid=traffic)
                                    AdspotsInAv.save()
                                    record_inserted = 1
            last_id_playlist = Playlist.id_playlist
            xmlfilename = GenerateXMLfromDatabase(daydate, channel_id, channel_zone.id_zone_channel, str(new_version), str(max_version_draft))
            path_inftp = channeldata.ftp_channel_name+'/schedules/'+channel_zone.region
            # uploadFTP(useraccess.ftp_server, useraccess.ftp_port, useraccess.ftp_user, useraccess.ftp_password, xmlfilename , path_inftp)

            ############ Display data on view_playlist_id page ##################
            return redirect("playlists:view_playlist", id_playlist=last_id_playlist)
        else:
            id_user = user
            useraccess = Useraccess.objects.get(id_user=id_user)
            channel_id = request.POST.get('channel_id')
            channeldata = Channels.objects.get(id_channel=channel_id)
            zonename = request.POST.get('zonename')
            daydate = request.POST.get('day')
            number_of_windows = request.POST.get('numofwin')
            #return HttpResponse(number_of_windows)
            channel_zone = ChannelsZone.objects.get(id_channel=channel_id, zonename=zonename)
            version = request.POST.get('version')

            daydate = datetime.datetime.strptime(str(daydate), '%Y-%m-%d')
            daydate = daydate.strftime('%Y-%m-%d')
            start_date = str(daydate) + "T00:01:00+00:00"
            end_date = str(daydate) + "T23:59:00+00:00"
            now = datetime.datetime.now()

            max_version = Playlists.objects.filter(broadcast_date=str(daydate)).aggregate(Max('version')).get('version__max')
            new_version = int(max_version)

            max_version_draft = Playlists.objects.filter(broadcast_date=str(daydate)).aggregate(Max('draft_version')).get('draft_version__max')
            new_version_draft = int(max_version_draft)
            Playlist = Playlists(
                id_channel_id=channel_id,
                version=int(max_version), 
                broadcast_date=str(daydate), 
                start_date=start_date, 
                end_date=end_date,  
                id_zone_channel_id=channel_zone.id_zone_channel,
                is_draft='1',
                draft_version=int(max_version_draft)+1
            )
            Playlist.save()
            traffic = 0
            record_inserted = 0
            var_test = 0
            for i in range(int(number_of_windows)):
                if request.POST.get('numofavails['+str(i)+']'):
                    numofavails = request.POST.get('numofavails['+str(i)+']')
                    window_start = request.POST.get('windowstart['+str(i)+']')
                    window_start = daydate+' '+window_start+':00'
                    window_end = request.POST.get('windowend['+str(i)+']')
                    window_end = daydate+' '+window_end+':00'
                    FMT = '%Y-%m-%d %H:%M:%S'
                    window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                    window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                    window_duration = window_duration.strftime('%H%M%S00')
                    Window = Windows(id_playlist_id=Playlist.id_playlist, window_start=window_start, window_end=window_end, window_duration=window_duration )
                    Window.save()

                    for j in range(int(numofavails)):
                        if request.POST.get('availstart['+str(i)+']['+str(j)+']'):
                            av_start = request.POST.get('availstart['+str(i)+']['+str(j)+']')
                            av_start = daydate+' '+av_start+':00'
                            number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                            Avail = Avails(id_window_id=Window.id_window, avail_start=av_start, availinwindow=str(j+1), datetime=now )
                            Avail.save()

                            for k in range(int(number_of_ads)):
                                if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                                    adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                                    traffic +=1
                                    AdspotsInAv = AdspotsInAvail(id_avail_id=Avail.id_avail, id_adspot_id=adspot, positioninavail=str(k+1), trafficid=traffic)
                                    AdspotsInAv.save()
                                    record_inserted = 1
            last_id_playlist = Playlist.id_playlist
            # xmlfilename = GenerateXMLfromDatabase(daydate, channel_id, channel_zone.id_zone_channel, str(new_version) )
            # path_inftp = channeldata.ftp_channel_name+'/schedules/'+channel_zone.region
            # uploadFTP(useraccess.ftp_server, useraccess.ftp_port, useraccess.ftp_user, useraccess.ftp_password, xmlfilename , path_inftp)

            ############ Display data on view_playlist_id page ##################
            return redirect("playlist:draft_playlist")





@login_required
def edit_playlist_old(request,id_playlist="1"):
    if request.method == 'POST':
        playlist = Playlists.objects.get(pk=id_playlist)
        channels = Channels.objects.filter(id_user=user)
        region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
        d = playlist.broadcast_date

        windows = Windows.objects.filter(id_playlist=playlist.id_playlist)

        win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)
        avails = Avails.objects.filter(id_window__in=win).values_list('id_avail', flat=True)
        av = Avails.objects.filter(id_window__in=win);
        adspots = AdspotsInAvail.objects.filter(id_avail__in=avails)

        data = {'playlist': playlist, 'channels': channels,'region':region,'d':d,'windows':windows,'adspots':adspots, 'av':av }
        return render(request, "core/edit_playlist_id.html", data)
    else:
        id_session = str(user)
        channels = Channels.objects.filter(id_user=id_session).values_list('id_channel', flat=True)
        playlists = Playlists.objects.filter(id_channel__in=channels).order_by('-id_playlist')
        data = {'playlists': playlists}
        return render(request, "core/edit_playlist.html",data)


@login_required
def edit_older_playlist(request,id_playlist="1"):
    if request.method == 'POST':
        edit_btn = request.POST.get("edit_btn")
        view_btn = request.POST.get("view_btn")
        insertion_results_btn = request.POST.get("insertion_results_btn")
        duplicate_btn = request.POST.get("duplicate_btn")
        draft_btn = request.POST.get("draft_btn")
        if(edit_btn):
            playlist = Playlists.objects.get(pk=id_playlist)
            channels = Channels.objects.filter(id_user=user)
            region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
            d = playlist.broadcast_date

            win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

            data = {}
            data["windows"] = []
            data["number_of_wins"] = 0
            i = 0

            windows = Windows.objects.filter(id_playlist=playlist.id_playlist).order_by('window_start')
            for window in windows:
                window_dic = {}
                window_dic['i'] = i
                i = i+1
                window_dic['id_window'] = window.id_window
                window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
                window_start_formated_2 = window_start_formated.strftime("%H:%M")
                window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
                window_end_formated_2 = window_end_formated.strftime("%H:%M")
                window_dic['window_start'] = window_start_formated_2
                window_dic['window_end'] = window_end_formated_2
                window_dic['avails_in_win'] = []
                window_dic['num_of_avails'] = 0
                data["number_of_wins"] = i
                avails = Avails.objects.filter(id_window=window.id_window)
                j = 0
                for avail in avails:
                    avail_dic = {}
                    avail_dic["j"] = j
                    j = j+1
                    avail_dic["id_avail"] = avail.id_avail
                    avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                    avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                    avail_dic["avail_start"] = avail_start_formated2
                    avail_dic["adspots_in_avail"] = []
                    window_dic["avails_in_win"].append(avail_dic)
                    adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                    window_dic['num_of_avails'] = j
                    k = 0
                    avail_dic["num_of_adspots"] = 0
                    for adspot in adspots:
                        adspot_dic = {}
                        adspot_dic["k"] = k
                        k = k+1
                        avail_dic["num_of_adspots"] = k
                        adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                        adspot_dic["id_adspot"] = adspot.id_adspot
                        avail_dic["adspots_in_avail"].append(adspot_dic)
                data["windows"].append(window_dic)


            now = datetime.datetime.now()
            activite = 'Edit PlayList'
            desc = 'Admin Edit PlayList  id: ' + str(playlist.id_playlist)
            activity = Activity(activity=activite , date=now ,description=desc )
            activity.save()

            data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
            return render(request, "core/edit_playlist_id.html", data_playlist)
        elif(duplicate_btn):
            playlist = Playlists.objects.get(pk=id_playlist)
            channels = Channels.objects.filter(id_user=user)
            region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
            d = playlist.broadcast_date

            win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)

            data = {}
            data["windows"] = []
            data["number_of_wins"] = 0
            i = 0

            windows = Windows.objects.filter(id_playlist=playlist.id_playlist)
            for window in windows:
                window_dic = {}
                window_dic['i'] = i
                i = i+1
                window_dic['id_window'] = window.id_window
                window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
                window_start_formated_2 = window_start_formated.strftime("%H:%M")
                window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
                window_end_formated_2 = window_end_formated.strftime("%H:%M")
                window_dic['window_start'] = window_start_formated_2
                window_dic['window_end'] = window_end_formated_2
                window_dic['avails_in_win'] = []
                window_dic['num_of_avails'] = 0
                data["number_of_wins"] = i
                avails = Avails.objects.filter(id_window=window.id_window)
                j = 0
                for avail in avails:
                    avail_dic = {}
                    avail_dic["j"] = j
                    j = j+1
                    avail_dic["id_avail"] = avail.id_avail
                    avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
                    avail_start_formated2 = avail_start_formated.strftime("%H:%M")
                    avail_dic["avail_start"] = avail_start_formated2
                    avail_dic["adspots_in_avail"] = []
                    window_dic["avails_in_win"].append(avail_dic)
                    adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
                    window_dic['num_of_avails'] = j
                    k = 0
                    avail_dic["num_of_adspots"] = 0
                    for adspot in adspots:
                        adspot_dic = {}
                        adspot_dic["k"] = k
                        k = k+1
                        avail_dic["num_of_adspots"] = k
                        adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                        adspot_dic["id_adspot"] = adspot.id_adspot
                        avail_dic["adspots_in_avail"].append(adspot_dic)
                data["windows"].append(window_dic)


            data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"]}
            return render(request, "core/duplicate_playlist_id.html", data_playlist)
        elif(view_btn):
            return redirect("playlists:view_playlist", id_playlist=id_playlist)
        else:
            return redirect("playlist:insertion_results", id_playlist=id_playlist)
    else:
        now = datetime.datetime.now() - timedelta(days=30)
        id_session = str(user)
        channels = Channels.objects.filter(id_user=id_session).values_list('id_channel', flat=True)
        playlists = Playlists.objects.filter(id_channel__in=channels,is_draft='0',start_date__lte=now).order_by('-broadcast_date')

        data = {'playlists': playlists}
        return render(request, "core/edit_older_playlist.html",data)


@login_required
def new_playlist_old(request):
    if request.method == 'POST':

        useraccess = Useraccess.objects.get(id_user=user)
        channel_id = request.POST.get('channel_id')
        channeldata = Channels.objects.get(id_channel=channel_id)
        zonename = request.POST.get('zonename')
        daydate = request.POST.get('day')
        number_of_windows = request.POST.get('numofwin')
        channel_zone = ChannelsZone.objects.get(id_channel=channel_id, zonename=zonename)
        print('TYYYYYYYYYYYYYYYYYYYYYPE',type(channel_zone))
        print('channel_zone',channel_zone)
        daydate = datetime.datetime.strptime(str(daydate), '%m/%d/%Y')
        daydate = daydate.strftime('%Y-%m-%d')
        start_date = str(daydate) + "T00:01:00+00:00"
        end_date = str(daydate) + "T23:59:00+00:00"
        now = datetime.datetime.now()
        Playlist = Playlists(
            id_channel_id=channel_id,
            version="1", 
            broadcast_date=str(daydate), 
            start_date=start_date, 
            end_date=end_date,  
            id_zone_channel_id=channel_zone.id_zone_channel
        )
        Playlist.save()
        traffic = 0
        # starts =[]
        for i in range(int(number_of_windows)):
            number_of_ads = request.POST.get('numofads['+str(i)+']')
            if request.POST.get('numofads['+str(i)+']'):
                number_of_ads = request.POST.get('numofads['+str(i)+']')
                window_start = request.POST.get('windowstart['+str(i)+']')
                window_start = daydate+' '+window_start+':00'
                window_end = request.POST.get('windowend['+str(i)+']')
                window_end = daydate+' '+window_end+':00'
                FMT = '%Y-%m-%d %H:%M:%S'
                window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
                window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
                window_duration = window_duration.strftime('%H%M%S00')

                Window = Windows(id_playlist_id=Playlist.id_playlist, window_start=window_start, window_end=window_end, window_duration=window_duration )
                Window.save()
                Avail = Avails(id_window_id=Window.id_window, avail_start=window_start, availinwindow='1', datetime=now )
                Avail.save()
                for j in range(int(number_of_ads)):
                    if request.POST.get('ad['+str(i)+']['+str(j)+']'):
                        adspot = request.POST.get('ad['+str(i)+']['+str(j)+']')
                        traffic +=1
                        AdspotsInAv = AdspotsInAvail(id_avail_id=Avail.id_avail, id_adspot_id=adspot, positioninavail=str(j+1), trafficid=traffic)
                        AdspotsInAv.save()
        xmlfilename = GenerateXMLfromDatabase(daydate, channel_id, channel_zone.id_zone_channel, '1' )
        path_inftp = channeldata.ftp_channel_name+'/schedules/'+channel_zone.region
        # uploadFTP(useraccess.ftp_server, useraccess.ftp_port, useraccess.ftp_user, useraccess.ftp_password, xmlfilename , path_inftp)
        # channels = Channels.objects.filter(id_user=user)
        return render(request, "core/new_playlist.html")
    else:
        channels = Channels.objects.filter(id_user=user)
        return render(request, "core/new_playlist.html",{'data': {'channels': channels}})


@login_required
def test_options(request):
    if request.method =='POST':
        options = request.POST.get('optionsname')
        print(options)
    return render(request, "core/test_options.html")


@login_required
def expande(request):
    id_playlist = request.GET.get('id_playlist')
    playlist = Playlists.objects.get(pk=id_playlist)
    channels = Channels.objects.get(id_channel=playlist.id_channel.id_channel)
    region = ChannelsZone.objects.get(id_zone_channel=playlist.id_zone_channel.id_zone_channel)
    ftp_channel_name = channels.ftp_channel_name
    networkname = channels.networkname
    zonename = region.zonename
    broadcast_date = playlist.broadcast_date.replace("-","")
    result = Verifs.objects.filter(networkname=networkname,zonename=zonename,broadcast_date=broadcast_date).last()
    d = playlist.broadcast_date
    broadcast_date_verif = str(playlist.broadcast_date).replace("-","")
    win = Windows.objects.filter(id_playlist=playlist.id_playlist).values_list('id_window', flat=True)
    data = {}
    data["windows"] = []
    data["number_of_wins"] = 0
    i = 0
    windows = Windows.objects.filter(id_playlist=playlist)
    for window in windows:
        window_dic = {}
        window_dic['i'] = i
        i = i+1
        window_dic['id_window'] = window.id_window
        window_start_formated = datetime.datetime.strptime(window.window_start, '%Y-%m-%d %H:%M:%S')
        window_start_formated_2 = window_start_formated.strftime("%H:%M")
        window_end_formated = datetime.datetime.strptime(window.window_end, '%Y-%m-%d %H:%M:%S')
        window_end_formated_2 = window_end_formated.strftime("%H:%M")
        window_dic['window_start'] = window_start_formated_2
        window_dic['window_end'] = window_end_formated_2
        window_dic['avails_in_win'] = []
        window_dic['num_of_avails'] = 0
        data["number_of_wins"] = i
        avails = Avails.objects.filter(id_window=window.id_window)
        j = 0
        for avail in avails:
            avail_dic = {}
            avail_dic["j"] = j
            j = j+1
            avail_dic["id_avail"] = avail.id_avail
            avail_start_formated = datetime.datetime.strptime(avail.avail_start, '%Y-%m-%d %H:%M:%S')
            avail_start_formated2 = avail_start_formated.strftime("%H:%M")
            avail_dic["avail_start"] = avail_start_formated2
            avail_dic["adspots_in_avail"] = []
            window_dic["avails_in_win"].append(avail_dic)
            adspots = AdspotsInAvail.objects.filter(id_avail=avail.id_avail)
            window_dic['num_of_avails'] = j
            k = 0
            avail_dic["num_of_adspots"] = 0
            for adspot in adspots:
                adspot_dic = {}
                adspot_dic["k"] = k
                k = k+1
                avail_dic["num_of_adspots"] = k
                adspot_dic["id_adsinavail"] = adspot.id_adsinavail
                adspot_dic["id_adspot"] = adspot.id_adspot
                print("Wait I'm in database")
                try:
                    result = Verifs.objects.filter(broadcast_date = broadcast_date_verif, trafficId = adspot.trafficid, revision__lte = int(playlist.version)).latest('id_verif')
                    adspot_dic["airStatusCode"] = result.airStatuscode
                    adspot_dic["airTime"] = result.airTime
                except Verifs.DoesNotExist:
                    print('oups')
                else:
                    print("file not ready yet")
                avail_dic["adspots_in_avail"].append(adspot_dic)
        data["windows"].append(window_dic)
        record_inserted = 0
    data_playlist = {'data':data["windows"],'playlist': playlist, 'channels': channels,'region':region,'d':d,'number_of_wins':data["number_of_wins"],'record_inserted':record_inserted}
    return render(request, "core/expande.html", data_playlist)


@login_required
def adspost_avail():
    from datetime import datetime
    now = datetime.now()
    campaigns = Placement.objects.filter(id_channel=1).values_list('id_campaign')

    campaigns = [i[0] for i in campaigns ]
    adspot = Campaigns.objects.filter(id_campaign__in = campaigns , end_day__lt=now).values_list('id_adpost').distinct()
    adspot = [i[0] for i in adspot]

    avail = AdspotsInAvail.objects.filter(id_adspot__in=adspot)
    avail = [av[0] for av in avail]


@login_required
def delete_avail(request):
    from datetime import datetime ,timedelta
    from iteration_utilities import deepflatten

    channel2 = request.GET.get('channel')
    playlist = request.GET.get('playlist')
    region =  request.GET.get('region')
    result = []
    channel = Channels.objects.get(id_channel=channel2)
    print(channel)
    channel_id = int(channel2)
    channel_networkname = channel.networkname
    now = datetime.now()

    if playlist != None:
        now = datetime.strptime(playlist,   '%Y-%m-%d')

    broadcast_playlist = now.strftime('%Y-%m-%d')
    broadcast_verif = now.strftime('%Y%m%d')
    n = now.strftime('%Y-%m-%d')


    print(channel)
    print(type(channel))
    print(region)
    data = Playlists.objects.last()
    print(data)
    playlists=[]
    # if region != None :
    #     region =ChannelsZone.objects.get(zonename=region)
    #
    #     playlists = Playlists.objects.filter(id_zone_channel=region)
    # if channel != None :
    #     channel = Channels.objects.get(id_channel=channel)
    #     if len(playlists)==0:
    #         playlists = Playlists.objects.filter(id_channel=channel)
    #     else :
    #         playlists = playlists.filter(id_channel=channel)
    # if playlist != None:
    #     now = datetime.strptime(playlist,   '%Y-%m-%d')
    #     n= now.strftime('%Y-%m-%d')
    #     t = datetime.strptime(n,'%Y-%m-%d') +timedelta(hours=4)
    #     #data = data.filter(start_date__gte=playlist, end_date__lt=playlist1 )
    # else :
    #     now = datetime.now()
    #     n= now.strftime('%Y-%m-%d')
    #     t = datetime.strptime(n,'%Y-%m-%d') +timedelta(hours=4)
    print(playlists)

    from django.db import connection
    cursor = connection.cursor()


    queries = """
                    SELECT Avails.id_avail FROM Windows
                    left join Playlists on Playlists.id_playlist = Windows.id_playlist
                    LEFT JOIN Avails on Avails.id_window = Windows.id_window
                    LEFT JOIN Adspots_in_avail on Adspots_in_avail.id_avail = Avails.id_avail
                    LEFT JOIN Verifs on (Verifs.trafficId = Adspots_in_avail.trafficId and Verifs.broadcast_date =  %s and Verifs.networkname = %s)
                    where Verifs.airStatusCode = "1005" and Playlists.id_channel = %s and Playlists.id_playlist in (Select max(id_playlist) from Playlists where Playlists.broadcast_date = %s group by id_zone_channel order by Playlists.version desc) group by Avails.id_avail limit 3
                  """
    print(queries)
    data_tuple=(broadcast_verif, channel_networkname, channel_id, broadcast_playlist )
    cursor.execute(queries,data_tuple)
    row = cursor.fetchall()
    print("row")
    print(row)


    # windows = Windows.objects.filter(window_start__gte=now,window_end__lt=t).select_related('id_playlist').filter(broadcast_date = n).last().order_by('window_start')[:3]
    # windows = Windows.objects.filter(window_start__gte=now,window_end__lt=t,id_playlist__in=playlists).order_by('window_start')[:3]

    # if len(playlists) > 0 :
    #     windows = Windows.objects.filter(window_start__gte=now,window_end__lt=t,id_playlist__in=playlists).order_by('window_start')[:3]
    # else :
    #     windows = Windows.objects.filter(id_playlist=data).order_by('window_start')[:3]

    for id_avs in row:
        for id_av in id_avs:
            avail = Avails.objects.get(pk=id_av)
            av={}
            av['id_avail'] = avail.id_avail
            av['start'] = avail.avail_start
            av['adspot'] = ""
            adspots = AdspotsInAvail.objects.filter(id_avail=avail)
            av['somme'] = 0
            av['duration' ]=""
            for adspot in adspots :
                av['adspot'] += " / " + adspot.id_adspot.adspot_name
                av['duration'] +=  " / " + str(adspot.id_adspot.duration)
                av['somme'] += int(adspot.id_adspot.duration)

            result.append(av)

            avail=''


    return render(request,'core/avails_details.html' ,{'avails':result, 'queries':row})


@login_required
def pending(request):

    urls=Pending.objects.all()
    return render(request, 'core/pending.html',context={'urls':urls})


@login_required
def generate_playlist_from_prediction(request):
    if request.method == 'POST':
        # get day + channel + zone + user_id
        useraccess = Useraccess.objects.get(id_user=user)
        channel_id = request.POST.get('channel_id')
        channeldata = Channels.objects.get(id_channel=channel_id)
        zonename = request.POST.get('zonename')
        daydate = request.POST.get('day')
        channel_zone = ChannelsZone.objects.get(id_channel=channel_id, zonename=zonename)


        # generate playlist with fixed windows

        daydate = datetime.datetime.strptime(str(daydate), '%m/%d/%Y')
        daydate = daydate.strftime('%Y-%m-%d')

        active_campaigns = Campaigns.objects.filter(id_user_id=user, start_day__lte=str(daydate), end_day__gte=str(daydate))
        print(active_campaigns)

        start_date = str(daydate) + "T00:01:00+00:00"
        end_date = str(daydate) + "T23:59:00+00:00"
        now = datetime.datetime.now()
        Playlist = Playlists(
            id_channel_id=channel_id,
            version="1", 
            broadcast_date=str(daydate), 
            start_date=start_date, 
            end_date=end_date,  
            id_zone_channel_id=channel_zone.id_zone_channel,
            is_draft='0',
            draft_version='0'
        )
        Playlist.save()
        traffic = 0
        record_inserted = 0
        day_times = DayTime.objects.exclude(id_time = 13)
        for day_time in day_times:
            # if request.POST.get('numofavails['+str(i)+']'):
            # numofavails = request.POST.get('numofavails['+str(i)+']')

            window_start = day_time.start
            window_start = daydate+' '+window_start+':00'
            window_end = day_time.end
            window_end = daydate+' '+window_end+':00'
            FMT = '%Y-%m-%d %H:%M:%S'
            window_duration = datetime.datetime.strptime(window_end, FMT) - datetime.datetime.strptime(window_start, FMT)
            window_duration = datetime.datetime.strptime(str(window_duration), '%H:%M:%S')
            window_duration = window_duration.strftime('%H%M%S00')
            Window = Windows(id_playlist_id=Playlist.id_playlist, window_start=window_start, window_end=window_end, window_duration=window_duration )
            Window.save()
            # for campaign in active_campaigns:
            #     camp_in_widnow = Placement.objects.filter(id)
            adbreaks_predected_in_window = Adbreak_predict.objects.filter(time__lt=day_time.end, time__gte=day_time.start).filter(day=daydate, id_channel = channel_id ).order_by('time')
            adbreaks_predected_in_window = adbreaks_predected_in_window.exclude(time=day_time.end)

            if not adbreaks_predected_in_window:
                Window.delete()
            j = 0


            for adbreak in adbreaks_predected_in_window:

                av_start = adbreak.time
                av_start = daydate+' '+av_start+':00'
                # number_of_ads = request.POST.get('numofads['+str(i)+']['+str(j)+']')
                Avail = Avails(id_window_id=Window.id_window, avail_start=av_start, availinwindow=str(j+1), datetime=now )
                Avail.save()
                j = j+1

                # for campaign in active_campaigns:
                #     camp_in_widnow = Placement.objects.filter(id_campaign = campaign.id_campaign, id_time = day_time.id_time, id_channel = channel_id )
                #     if camp_in_widnow:

                    # for k in range(int(number_of_ads)):
                    #     if request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']'):
                    #         adspot = request.POST.get('ad['+str(i)+']['+str(j)+']['+str(k)+']')
                    #         traffic +=1
                    #         AdspotsInAv = AdspotsInAvail(id_avail_id=Avail.id_avail, id_adspot_id=adspot, positioninavail=str(k+1), trafficid=traffic)
                    #         AdspotsInAv.save()



                # insert empty avails in those windows from adbreak predict
                # insert adposts from campaigns into those avails
        channels = Channels.objects.filter(id_user=user)
        return render(request, "core/generate_playlist_from_prediction.html",{'data': {'channels': channels}})

    channels = Channels.objects.filter(id_user=user)
    return render(request, "core/generate_playlist_from_prediction.html",{'data': {'channels': channels}})


class GetPlayListImpression(APIView):
    from rest_framework.response import Response


    def post(self, request, format=None):
        from collections import Counter
        from .utils import visioner_playlist
        if request.method == 'POST':
            playlist = request.data
            # print("Playlist: ",playlist)
            now=datetime.datetime.now()
            now_minus_week= now-datetime.timedelta(days=7)
            last_week_day = now_minus_week.strftime('%Y-%m-%d')
            last_week_minute = now_minus_week.strftime('%H:%M:00')

            # Assuming there's a field named 'timestamp' in your Epg model
            start_time = now_minus_week - timedelta(minutes=10)
            end_time = now_minus_week + timedelta(minutes=10)

            # Get SFR analytics volume for last week
            # try:
                # analytics_data = Sfr_analytics.objects.get(
                #     day=last_week_day,
                #     minute=last_week_minute,
                #     sfr_channel_name="2M Maroc"
                # )
                # total_volume = round(float(analytics_data.purcent) * 4500000 / 17)
                # print('Analytic SRF: ',analytics_data.minute)

            # except Sfr_analytics.DoesNotExist:
            #     total_volume = 0
            #     print({"message": "SFR Not Found"})
            #     return JsonResponse({'message':'SFR Not Found'})
            # finally:
        try:
            # get epg for last week based on start and interval
            # epg_data = Epg.objects.filter(start_time__lte=now_minus_week,end_time__gte=now_minus_week)
            # serialized_data = serialize('json', epg_data)
            # # Convert serialized data to Python data (list of dictionaries)
            # deserialized_data = json.loads(serialized_data)
            
            # call_vast.delay(
            #     emission_name=emission.emission_name,
            #     genre=emission.genre,
            #     epg_duration_in_seconds = (emission.end_time - emission.start_time).total_seconds(),
            #     total_volume = total_volume
            #     )
            
            # check if that ads is being replaced before
            if AdslotsVisionr.objects.filter(playlistdate=playlist['date'],subid=playlist['subId'])[0].status == "Completed":
                print("This Ad Has Already Been Replaced")
                return JsonResponse({"message":"This Ad Has Already Been Replace"})
            else:

                    

                processed_data = {
                        **playlist,
                        "date": playlist['date']
                        }
                # here we need to create playlist based on most frequanlty ads but we need to wait alma response
                print("Creating Playlist",playlist['date'])
                try:
                    most_common_title = Counter(item['title'] for item in visioner_playlist()).most_common(1)
                    if most_common_title:
                        common_title = most_common_title[0][0]
                        print("The most replaced ads is:",common_title)
                        for item in visioner_playlist():
                            if item['title'] == common_title:
                                # print("Full item details:", item)
                                pass
                    create_playlist_xml(processed_data)
                except Exception as e:
                    raise e
                # # Update Adslots Visioner Status
                adslot = AdslotsVisionr.objects.filter(playlistdate=playlist['date'],subid=playlist['subId'])[0]
                adslot.status = "Completed"
                adslot.save()
                # print([item['title'] for item in playlist])



                return JsonResponse({"message":"Alma Ads Has bees replaces Succesfully","status":"success"})
        except Epg.DoesNotExist:
            print("Update Epg Database")
            return JsonResponse({"message":"EPG Unsynchronized","status":"failed"})


@login_required
def process_adslot(reuqest):
    from datetime import datetime
    from .utils import TelegramLog
    # URL to fetch the playlist JSON
    url = "https://almatv-stor.vizionr.fr/synthesia/almatv/playlist/manager/php/_getPlaylist.php?fields=title,isPub,duration"
    playlists = []
    # Function to fetch and parse the playlist JSON from the URL
    def fetch_playlist_data(url):
        response = requests.get(url)
        if response.status_code == 200:
            return response.json()
        else:
            return None
    def insert_ad_slots(ad_slots_json):
        # check if subid already in database skip it
        date_format = "%Y-%m-%d"  # Adjust as necessary to match the format in your JSON
        visioner = AdslotsVisionr()
        for playlist in ad_slots_json:  # Assuming `ad_slots_json` is the parsed JSON data
            playlist_date_str = playlist.get("playlistDate", "")

            # Validate and format playlist_date
            try:
                playlist_date = datetime.strptime(playlist_date_str, date_format).date()
            except ValueError:
                # If there's an error parsing the date, use the current date as default
                playlist_date = datetime.now().date()

            for ad in playlist.get('data', []):
                if ad.get('isPub', 0) == '1':
                    try:

                        # Check if an object with the same values already exists
                        print("SUB ID: ",ad.get("subId"))
                        adslot = AdslotsVisionr.objects.get(
                            playlistdate = playlist.get("id"),
                            subid=f"{ad.get('subId')}",
                        )
                        print("Found Object",adslot)

                    except AdslotsVisionr.DoesNotExist:
                        visioner.adid = ad.get('id', ''),
                        visioner.subid = ad.get('subId', ''),
                        visioner.start = ad.get('start', None),
                        visioner.end = ad.get('end', None),
                        visioner.startts = ad.get('startTs', None),
                        visioner.endts = ad.get('endTs', None),
                        visioner.cut = ad.get('cut', None),
                        visioner.scenario = ad.get('scenario', ''),
                        visioner.duration = ad.get('duration', None),
                        visioner.ispub = ad.get('isPub', None),
                        visioner.title = ad.get('title', ''),
                        visioner.replacementadid = "",
                        visioner.replacementpath = "",
                        visioner.replacementduration = None
                        visioner.status = 'Pending',
                        visioner.updatesent = 0,
                        visioner.playlistdate = playlist_date
                        visioner.save()

                        # telegram = TelegramLog()
                        # telegram.send_telegram_log(f"Error While insert New Playlist {str(e)}")

        return playlists

    ad_slots = fetch_playlist_data(url)

    # print(ad_slots)
    if ad_slots:
        insert_ad_slots(ad_slots)
    else:
        print("Failed to fetch playlist data")
    return JsonResponse(playlists,safe=False, status=200)


class DynamicAdPlaylist(View):

    from apps.core.utils import TelegramLog

    # telegram_bot = TelegramLog(BOT_TOKEN="6723497869:AAEKCB3YJUGnUFeMihLlr-FHblTuvtoVUZA",GROUP_ID="-4153299009")
    telegram_bot = TelegramLog(BOT_TOKEN="6599658496:AAFdK7Gsm1LvgYCIw2o8_frcbte1yNh-w44",GROUP_ID="-4175287619")

    def get(self, request):
        import pytz
        from datetime import datetime, timedelta

        try:
            # Assigning identifiers for channel and regional data.
            channel_id = 1
            channel_name = "2M Monde"
            # Retrieving start date and duration parameters from the request.
            start_date_time_str = request.GET.get("start")
            duration_seconds = float(request.GET.get("duration", 20))
            region_test = request.GET.get("region", "France")
            # Parsing the start date and time string into a datetime object.
            start_datetime = datetime.strptime(start_date_time_str, "%Y-%m-%d %H:%M:%S.%f")
            # Define the timezone for France or Netherlands
            local_timezone = "Europe/Paris" # "Europe/Amsterdam"
            france_timezone = pytz.timezone(local_timezone)
            start_datetime_france = france_timezone.localize(start_datetime)
            # Define the timezone for Morocco
            morocco_timezone = pytz.timezone("Africa/Casablanca")
            start_datetime_morocco = morocco_timezone.localize(start_datetime)
            # Adjusting the start datetime by adding 2 hours to align with a specific timezone or scheduling requirement.
            start_datetime = start_datetime + timedelta(hours=2)
            # Ensuring timezone awareness for the start datetime to maintain consistency and prevent ambiguity.
            start_datetime = timezone.make_aware(start_datetime, timezone.get_current_timezone())
            # Extracting the date component from the timezone-aware start datetime for further processing or storage.
            # start_date = start_datetime_france.date()
            start_date = start_datetime.date()
            start_time = start_datetime.time()

            # Step 1: Create and save AdBreaks object based on resived data about the ad-break
            # Create and save AdBreaks object
            ad_break = Adbreaks.objects.create(
                start_at=start_datetime_morocco,
                duration=duration_seconds,
                id_channel=channel_id,
                channel_name=channel_name
            )

            # Step 2: Retrieve or create Playlist object With Window Based on ad-break duration
            # Retrieving the channel zone information based on the channel ID and region, selecting the first match if available.
            channel_zone = ChannelsZone.objects.filter(id_channel=channel_id, region=region_test).first()

            # Step 3: Retrieve Epg objects for the specified start_date and channel_id
            emissions = Epg.objects.filter(
                id_channel = channel_id,
                start_time__lte = start_datetime_morocco,
                end_time__gte = start_datetime_morocco
            )

            # Step 4: Retrieve campaigns for the date range and based on if emissions are retrieved and the count is one
            if emissions.exists() and emissions.count() == 1:
                # Retrieve campaigns for the date range and where emissions" category is in program_category
                emissions_genres = emissions.first().genre
                emissions_categories = emissions.first().category
                # print(emissions_categories)
                active_campaigns = Campaigns.objects.filter(
                    start_day__lte=start_date,
                    end_day__gte=start_date,
                    program_category__icontains=emissions_genres,
                    country=region_test.lower()
                )
            else:
                active_campaigns = Campaigns.objects.filter(
                    start_day__lte=start_date,
                    end_day__gte=start_date,
                    country=region_test.lower()
                )
            # Filter out campaigns that have reached their airtime limit
            active_campaigns = [
                # Iterate over active campaigns
                campaign for campaign in active_campaigns
                # Check if the number of airtime logs for the campaign on the start_date is less than the allowed broadcasts per day
                if Campaignairtimelog.objects.filter(
                    campaign=campaign,
                    airtime_start__date=start_date,
                    insertion_status=True
                ).count() < campaign.broadcasts_day
                # Check if there exist time intervals for the campaign where the start_time falls within the interval
                and CampaignTimeIntervals.objects.filter(
                    campaign=campaign,
                    start_time__lte=start_time,
                    end_time__gte=start_time
                ).exists()
            ]

            # Step 5: Calculate Priority Score For Each Active Campaign and save it in CampaignPriorityScores
            # List to store campaign IDs and priority scores
            priority_score_list = []
            # Iterate through active campaigns
            for campaign in active_campaigns:
                # Get the first emission from the list of emissions
                actual_emission = emissions.first()
                # Calculate TSA (Target Specificity Allocation)
                TSA = (
                    2 if campaign.exclusivity else                    # If campaign has exclusivity, TSA is 2
                    (1 if campaign.shows_preference and actual_emission and actual_emission.emission_name in campaign.shows_preference else   # If emission name is in preferred shows, TSA is 1
                    (0.5 if campaign.program_category and actual_emission and actual_emission.genre in campaign.program_category else 0))   # If emission genre is in category programs, TSA is 0.5 else TSA is 0
                )
                # Perform the query to get the count of already aired slots for the campaign
                already_aired_slots = Campaignairtimelog.objects.filter(
                    campaign = campaign,
                    airtime_start__date = start_date,
                    insertion_status = True
                ).count()
                # Calculate Airing Requirement Fulfillment (ARF)
                ARF = already_aired_slots / campaign.broadcasts_day
                # Parse string to date if it's a string, otherwise extract date part
                end_date = (datetime.strptime(campaign.end_day, "%Y-%m-%d").date() if isinstance(campaign.end_day, str) else campaign.end_day.date())
                # Calculate urgency (Trend (U)) as a factor inversely proportional to the number of days left until the campaign's end date
                U = 1 / ((end_date - datetime.now().date()).days + 1)
                # Get position preferences from the campaign table and transform them into a list :::> Convert the string to a list of strings
                position_preferences = ast.literal_eval(campaign.position_preference)
                # Define weights for each position preference, starting from 1
                weights = {"before": 1, "during": 2, "after": 3,}
                # Calculate the total sum of weights
                total_weight_sum = sum(weights.values())
                # Get the maximum weight
                max_weight = max(weights.values())
                # Calculate the normalized weights
                normalized_weights = {k: v / total_weight_sum for k, v in weights.items()}
                # Calculate the weighted sum of position preferences
                weighted_sum = sum(normalized_weights[preference] for preference in position_preferences)
                # Calculate the average position preference score (P) between 0 and 1
                P = weighted_sum / max_weight
                # Calculate priority score for the campaign, or set to None if emissions do not exist
                priority_score = calculate_priority_score(TSA=TSA, ARF=ARF, U=U, P=P )
                # Append campaign ID and priority score to the list
                priority_score_list.append({"campaign": campaign, "priority_score": priority_score })
                # Create CampaignPriorityScores object to store priority score
                try:
                    # Try to retrieve an existing CampaignPriorityScores object
                    priority_scores_obj = CampaignPriorityScores.objects.get(campaign=campaign)
                    # Update the existing object
                    priority_scores_obj.priority_score = priority_score
                    priority_scores_obj.save()
                except CampaignPriorityScores.DoesNotExist:
                    # Create a new CampaignPriorityScores object if it doesn't exist
                    CampaignPriorityScores.objects.create(
                        campaign=campaign,
                        priority_score=priority_score
                    )
            # Order priority_score_list from bigger to smaller priority scores
            priority_score_list = sorted(priority_score_list, key=lambda x: x["priority_score"], reverse=True)

            # Step 6:
            # List to store ad spots to be inserted
            ad_spots_to_insert = []
            # Initialize remaining duration_seconds
            remaining_duration_seconds = duration_seconds -  6 # 10

            # ??? Need To Be Updated To Set Max Ads In The Avail
            # !!! Upgrade 06-05-2024
            min_duration = 8 # 35
            # Check if duration is >= 60 seconds and region is Netherlands, or if region is France
            if (int(duration_seconds) >= min_duration and  region_test == "Netherlands") or region_test == "France" :

                # Iterate through priority_score_list
                for entry in priority_score_list:
                    # Retrieve ad spots for the current campaign with duration condition and ordered by duration
                    list_adspot = Adspots.objects.filter(
                        # id_channel=channel_id,
                        id_campaign = entry["campaign"].id_campaign,
                        duration__lte = remaining_duration_seconds
                    ).order_by("duration")
                    # Check if ad spots exist for the current campaign
                    if list_adspot.exists():
                        # Get the first ad spot with the shortest duration
                        ad_spot = list_adspot.first()
                        # # Randomly select an ad spot from those with the shortest duration
                        # ad_spot = random.choice(list_adspot)
                        # Check if ad_spots_to_insert is not empty then
                        if ad_spots_to_insert:
                            # from functools import reduce
                            # exclusion_conditions = reduce(lambda x, spot: x | Q(ad_spot_1=spot.id_adpost, ad_spot_2_id=ad_spot.id_adpost) | Q(ad_spot_1_id=ad_spot.id_adpost, ad_spot_2_id=spot.id_adpost), ad_spots_to_insert, Q())

                            # Initialize an empty Q object to store the exclusion conditions
                            exclusion_conditions = Q()
                            # Loop over the ad_spots_to_insert list
                            for spot in ad_spots_to_insert:
                                # Build the exclusion conditions for the current spot
                                exclusion_conditions |= Q(ad_spot_1=spot.id_adpost, ad_spot_2_id=ad_spot.id_adpost) | Q(ad_spot_1_id=ad_spot.id_adpost, ad_spot_2_id=spot.id_adpost)
                            # Check if the current ad_spot has an exclusion relationship with any of the ad_spots_to_insert
                            if not AdSpotExclusion.objects.filter(exclusion_conditions).exists():
                                # If no relation exists, proceed with :
                                # Calculate the remaining duration_seconds for the next campaign
                                remaining_duration_seconds -= ad_spot.duration
                                # Append the ad spot to the list of ad spots to be inserted
                                ad_spots_to_insert.append(ad_spot)
                            else:
                                # If an exclusion relationship exists, skip this ad_spot
                                print(f"Ad spot {ad_spot.id_adpost} has an exclusion relation with the already existing ad spots. Skipping...")
                        else :
                            # Calculate the remaining duration_seconds for the next campaign
                            remaining_duration_seconds -= ad_spot.duration
                            # Append the ad spot to the list of ad spots to be inserted
                            ad_spots_to_insert.append(ad_spot)


            playlist = None
            # Check if ad_spots_to_insert is not empty and its count is greater than or equal to 1
            if ad_spots_to_insert and len(ad_spots_to_insert) >= 1:

                # Retrieve all Adspots containing "Filler" in their adspot_name
                # adspot_fillers = Adspots.objects.filter(adspot_name__contains="Filler")
                # Get one random Adspot object from the queryset
                # random_filler_adspot = adspot_fillers.order_by("?").first()
                # Append the ad-filler spot to the list of ad spots to be inserted
                # ad_spots_to_insert.append(random_filler_adspot)
                # random_filler_adspots = adspot_fillers.order_by("?")[:4]  # Get 4 random adspots from the queryset
                # ad_spots_to_insert += list(random_filler_adspots)

                adspot_fillers = Adspots.objects.filter(adspot_name__contains="Filler_Ma_10m", status="1")
                random_filler_adspots = adspot_fillers
                ad_spots_to_insert += list(random_filler_adspots)  # Append the adspots to the list of ad spots to be inserted


                # !!! Edit Need To Test [Added At 06-05-2024 11:59:59 PM]

                # Querying playlists based on the broadcast date and channel zone ID, ordered by creation datetime in descending order.
                playlists = Playlists.objects.filter(
                    broadcast_date=f"{start_date}",
                    id_zone_channel_id=channel_zone.id_zone_channel
                ).order_by("-created_at")
                # Checking if playlists exist and ensuring there is at least one playlist available for further processing.
                if playlists.exists() and playlists.count() > 0:
                    # Fetching the first playlist object from the queryset, which represents the last inserted playlist, if available.
                    old_playlist = playlists.first()
                    # Fetch All Windows For The Definded Playlist
                    playlist_windows = Windows.objects.filter(id_playlist = old_playlist)
                    # Create a copy of the playlist object
                    playlist = old_playlist
                    playlist.id_playlist = None  # Set primary key to None to create a new object
                    playlist.version = f"{ playlists.count() + 1 }" 
                    playlist.save()
                    # Iterate over each window
                    for _, window in enumerate(playlist_windows):
                        # Get avails for the current window
                        window_avails = Avails.objects.filter( id_window = window )
                        # Create a new Window object for new Playlist
                        new_window = window
                        new_window.id_window = None  # Set primary key to None to create a new object
                        new_window.id_playlist = playlist
                        new_window.save()
                        # Iterate over each avail for the current window
                        for _, avail in enumerate(window_avails):
                            # Get AdSpotsInAvail for the current avail
                            adspots_in_avail = AdspotsInAvail.objects.filter(id_avail=avail)
                            # Create a new Avail object for new Window
                            new_avail = avail
                            new_avail.id_avail = None  # Set primary key to None to create a new object
                            new_avail.id_window = new_window
                            new_avail.save()
                            # Iterate over each AdSpotInAvail for the current avail
                            for _, adspot_in_avail in enumerate(adspots_in_avail):
                                # Create a new Avail object for new Window
                                old_adspot_in_avail = adspot_in_avail
                                old_adspot_in_avail.id_adsinavail = None  # Set primary key to None to create a new object
                                old_adspot_in_avail.id_avail = new_avail
                                old_adspot_in_avail.save()
                else:
                    # Creating a new playlist object with the provided parameters and the current timezone-aware creation datetime.
                    playlist = Playlists.objects.create(
                        id_channel_id=channel_id ,
                        version="1",
                        broadcast_date=f"{start_date}",
                        start_date=f"{start_date}T00:01:00+00:00",
                        end_date=f"{start_date}T23:59:00+00:00", 
                        id_zone_channel_id=channel_zone.id_zone_channel,
                        is_draft="0",
                        draft_version="0"
                    )

                # Get All Windows For A Definded Playlist
                playlist_windows = Windows.objects.filter(id_playlist = playlist)
                # Create And Save New Window For Playlist Using Detected Ad-break Information With
                # A Fix Interval In 10 Minutes ( 10*60 = 600 seconds )
                window_durations = datetime.strptime(str(timedelta(seconds=(28*60 + int(duration_seconds)))), "%H:%M:%S")
                # window_durations = datetime.strptime(str(timedelta(seconds=(38*60 + int(duration_seconds)))), "%H:%M:%S")
                window_durations = window_durations.strftime("%H%M%S00")

                window_start = (start_datetime - timedelta(seconds=2*60) ).strftime("%Y-%m-%d %H:%M:%S")
                #??  we need to check if windows start is less then 12:00 am we need to get avail start time
                # window_start = (start_datetime - timedelta(seconds=12*60) ).strftime("%Y-%m-%d %H:%M:%S")
                window_end = (start_datetime + timedelta(seconds=(26*60 + int(duration_seconds))) ).strftime("%Y-%m-%d %H:%M:%S")
                # Check If The Playlist Has At least One Window
                # If The Playlist Has Not Been Initialized Yet With A Window Then
                if not playlist_windows.exists():
                    # Create And Save New Window
                    playlist_window = Windows.objects.create(
                        id_playlist = playlist,
                        window_start = window_start,
                        window_end = window_end,
                        window_duration = window_durations
                    )
                # If The Playlist Has Been Initialized With A Window Or A Window's List
                # We Will Get The Last Window
                else:
                    # Get The Last Window From The Windows List
                    playlist_window = playlist_windows.last()
                    # Get The Last Window Start Time And End Time Then Convert Them To DateTime Type
                    windows_start_at = datetime.strptime(playlist_window.window_start, "%Y-%m-%d %H:%M:%S")
                    windows_end_at = datetime.strptime(playlist_window.window_end, "%Y-%m-%d %H:%M:%S")
                    # Assuming windows_start_at and windows_end_at are timezone-naive datetimes
                    windows_start_at = timezone.make_aware(windows_start_at, timezone.get_current_timezone())
                    windows_end_at = timezone.make_aware(windows_end_at, timezone.get_current_timezone())
                    # Now check Check if the ad-break start time is within the window
                    if windows_start_at <= start_datetime <= windows_end_at:

                        # Convert the window duration string to a datetime object and add the duration_seconds
                        # window_durations = datetime.strptime(playlist_window.window_duration, "%H%M%S00") + datetime.strptime(str(timedelta(seconds=(10*60 + int(duration_seconds)))), "%H:%M:%S")
                        window_durations = datetime.strptime(playlist_window.window_duration, "%H%M%S00") + timedelta(seconds=(26*60 + int(duration_seconds)))
                        # Convert the resulting datetime object back to a string in the format "%H%M%S00"
                        window_durations = window_durations.strftime("%H%M%S00")

                        playlist_window.window_end = (windows_end_at + timedelta(minutes=26, seconds=duration_seconds)).strftime("%Y-%m-%d %H:%M:%S")
                        playlist_window.window_duration =  window_durations
                        playlist_window.save()
                    else:
                        # Create And Save New Window
                        playlist_window = Windows.objects.create(
                            id_playlist = playlist,
                            window_start = window_start,
                            window_end = window_end,
                            window_duration = window_durations
                        )
                # Count Of Window Avail In The Playlist Window
                window_avail_count = Avails.objects.filter( id_window = playlist_window ).count()
                # Create and save Window Avail object
                window_avail = Avails.objects.create(
                    id_window = playlist_window,
                    #?? fix this :: need to check
                    avail_start = start_datetime.strftime("%Y-%m-%d %H:%M:%S"),
                    availinwindow = f"{window_avail_count + 1}",
                    datetime = datetime.now()
                )
                #
                traffic = 0
                # Get the last inserted window in the playlist
                last_window = Windows.objects.filter(id_playlist=playlist).last()
                #
                if last_window:
                    # Get the last inserted avail in the window
                    last_avail = Avails.objects.filter(id_window=last_window).last()
                    #
                    if last_avail:
                        # Get the last inserted available link in the avail
                        last_avail_link = AdspotsInAvail.objects.filter(id_avail=last_avail).last()
                        #
                        if last_avail_link:
                            #
                            traffic = last_avail_link.trafficid
                #
                airtime_start = start_datetime
                #
                for index, ad_spot in enumerate(ad_spots_to_insert):
                    #
                    traffic +=1
                    #
                    AdspotsInAvail.objects.create(
                        id_avail = window_avail,
                        id_adspot = ad_spot,
                        positioninavail = index+1,
                        trafficid = traffic
                    )
                    #
                    # Check if a Campaignairtimelog with the same values already exists
                    existing_Campaignairtimelog = Campaignairtimelog.objects.filter(
                        campaign = ad_spot.id_campaign,
                        spot = ad_spot,
                        ad_break = ad_break
                    ).exists()
                    # If the entry doesn't exist, create it
                    if not existing_Campaignairtimelog:
                        Campaignairtimelog.objects.create(
                            campaign = ad_spot.id_campaign,
                            spot = ad_spot,
                            ad_break = ad_break,
                            airtime_start = airtime_start,
                            airtime_end = airtime_start + timedelta(seconds=ad_spot.duration),
                            insertion_status = True
                        )
                    #
                    airtime_start = airtime_start + timedelta(seconds=ad_spot.duration)
                #
                xml_playlist_res = generateSchedule(playlist)
                # Check the result
                if xml_playlist_res["status"]:
                    ftp_host = "172.16.205.1"
                    ftp_port =  60000
                    ftp_username = "SanoaMedia"
                    ftp_password = "SanoaMedia"
                    local_file_path = xml_playlist_res["file"]
                    if playlist.id_zone_channel.networkname == "REGNL":
                        remote_file_path = "2M/schedules/REG1_NL"
                        # uploadFTP(ftp_server, ftp_port, ftp_user, ftp_password, xml_file_path , ftp_upload_path)
                        ftp = FTPConnector(ftp_host, ftp_port, ftp_username, ftp_password)
                        # Upload a file to the server
                        ftp.upload_file(local_file_path, remote_file_path)
                    elif playlist.id_zone_channel.networkname == "2M":
                        remote_file_path = "2M/schedules/REG1_FR"
                        # # uploadFTP(ftp_server, ftp_port, ftp_user, ftp_password, xml_file_path , ftp_upload_path)
                        # ftp = FTPConnector(ftp_host, ftp_port, ftp_username, ftp_password)
                        # # Upload a file to the server
                        # ftp.upload_file(local_file_path, remote_file_path)
                else:
                    print(f"Failed to generate playlist file. Error: {xml_playlist_res['message']}")

            # send Message to telegram
            message_campaign_score = ' '.join(f" * [{campaign_score['campaign'].id_campaign}][{campaign_score['campaign'].name}][{campaign_score['priority_score']}] \n" for campaign_score in priority_score_list)
            alert_message = (
                "🚨 AD-Break Detected! 🚨\n"
                f"Detected At: {start_date_time_str} \n"
                f"====================\n"
                f"Region : {region_test} \n"
                f"====================\n"
                f"With Duration: {duration_seconds } Seconds \n"
                f"====================\n"
                f"With Duration To Be Replaced: {duration_seconds - 10 } Seconds \n"
                f"==================== \n"
                f"This Will Update Playlist With ID: {playlist.id_playlist if playlist != None else ''} \n"
                f"====================\n"
                f"Based On Emission: {emissions.first().emission_name if emissions.first() else ''} With Genre {emissions.first().genre if emissions.first() else ''} \n"
                f"====================\n"
                f"With Active Campaigns \n {message_campaign_score}"
                f"====================\n"
                f"With This Ad_Spots {[ ad_spot.adspot_name  for ad_spot in ad_spots_to_insert]}"
            )
            self.telegram_bot.send_telegram_log(alert_message)

            return JsonResponse({"message": "Ad playlist created successfully"}, status=200)

        except Exception as e:
            raise e


class StaticVerifsValidation(View):
    """
        A view to handle static verifications validation.

        This view is responsible for handling GET requests related to static verifications validation
        for a playlist identified by its primary key id.
    """
    def get(self, request, playlist_id):
        """
            Handle GET requests.

            Retrieve the playlist object with the specified primary key `playlist_id`.
            Retrieve all adbreaks and windows associated with the playlist.
            For each window, retrieve adbreaks within the window and corresponding avails.

            Args:
                request (HttpRequest): The HTTP request object.
                playlist_id (int): The primary key of the playlist to retrieve.

            Returns:
                HttpResponse: A JSON response containing the adbreaks, windows, and adspots information.
        """
        from datetime import datetime, timedelta
        # Retrieve the playlist object with the specified primary key id_playlist
        playlist = Playlists.objects.filter(id_playlist=playlist_id)
        if playlist:
            playlist = playlist.first()
            # Calculate the broadcast date by replacing dashes in the playlist's broadcast date
            broadcast_date = playlist.broadcast_date.replace("-", "")
            # Retrieve all adbreaks associated with the playlist's start date
            adbreaks = Adbreaks.objects.filter(start_at__date=playlist.broadcast_date)
            # Retrieve all windows associated with the playlist
            windows = Windows.objects.filter(id_playlist=playlist.id_playlist)
            #
            static_verifs = []
            # Iterate through each window
            for window in windows:
                # Retrieve adbreaks within the current window
                window_ad_start =  datetime.strptime(window.window_start, "%Y-%m-%d %H:%M:%S") - timedelta(hours=2)
                window_ad_end =  datetime.strptime(window.window_end, "%Y-%m-%d %H:%M:%S") - timedelta(hours=2)
                adbreaks_in_window = Adbreaks.objects.filter(
                    start_at__gte=window_ad_start,
                    start_at__lte=window_ad_end
                )
                # Retrieve avails associated with the current window
                window_avails = Avails.objects.filter(id_window=window)

                avails_count = window_avails.count()
                adbreaks_count = adbreaks_in_window.count()

                if avails_count <= adbreaks_count:
                    # Iterate through each avail
                    for index, avail in enumerate(window_avails):
                        # Retrieve adspots within the current avail
                        adspots_in_avail = AdspotsInAvail.objects.filter(id_avail=avail)
                        #
                        remaining_duration_seconds = adbreaks_in_window[index].duration
                        #
                        airTime = adbreaks_in_window[index].start_at
                        for adspot_in_avail in adspots_in_avail:
                            verif_spot = {
                                "networkname": playlist.id_zone_channel.networkname,
                                "zonename": playlist.id_zone_channel.zonename,
                                "broadcast_date": broadcast_date,
                                "trafficId": adspot_in_avail.trafficid,
                                "spotId": adspot_in_avail.id_adspot.adspot_name,
                                "airTime": airTime.strftime("%Y-%m-%d %H:%M:%S"),
                                "airLength": time.strftime("%H%M%S00", time.gmtime(int(adspot_in_avail.id_adspot.duration))),
                                "airStatusCode": "0001" if remaining_duration_seconds >= adspot_in_avail.id_adspot.duration else "0008",
                                "revision": playlist.version,
                                "is_active": True
                            }
                            # Or Add It To DataBase
                            new_ad_verif = Verifs(
                                networkname= playlist.id_zone_channel.networkname,
                                zonename= playlist.id_zone_channel.zonename,
                                broadcast_date= broadcast_date,
                                trafficId= adspot_in_avail.trafficid,
                                spotId= adspot_in_avail.id_adspot.adspot_name,
                                airTime= airTime.strftime("%Y-%m-%d %H:%M:%S"),
                                airLength= time.strftime("%H%M%S00", time.gmtime(int(adspot_in_avail.id_adspot.duration))),
                                airStatuscode= "0001" if remaining_duration_seconds >= adspot_in_avail.id_adspot.duration else "0008",
                                revision= playlist.version,
                                vercomplete = True
                            )
                            new_ad_verif.save()
                            remaining_duration_seconds -= adspot_in_avail.id_adspot.duration
                            airTime += timedelta(seconds=adspot_in_avail.id_adspot.duration)
                            # Append verif_spot to static_verifs
                            static_verifs.append(verif_spot)
                else:
                    # Iterate through each adbreak
                    for index, adbreak in enumerate(adbreaks_in_window):
                        # Retrieve adspots within the current avail
                        adspots_in_avail = AdspotsInAvail.objects.filter(id_avail=window_avails[index])
                        #
                        remaining_duration_seconds = adbreak.duration
                        #
                        airTime = adbreak.start_at
                        for adspot_in_avail in adspots_in_avail:
                            verif_spot = {
                                "networkname": playlist.id_zone_channel.networkname,
                                "zonename": playlist.id_zone_channel.zonename,
                                "broadcast_date": broadcast_date,
                                "trafficId": adspot_in_avail.trafficid,
                                "spotId": adspot_in_avail.id_adspot.adspot_name,
                                "airTime": airTime.strftime("%Y-%m-%d %H:%M:%S"),
                                "airLength": time.strftime("%H%M%S00", time.gmtime(int(adspot_in_avail.id_adspot.duration))),
                                "airStatusCode": "0001" if remaining_duration_seconds >= adspot_in_avail.id_adspot.duration else "0008",
                                "revision": playlist.version,
                                "is_active": True
                            }
                            # Or Add It To DataBase
                            new_ad_verif = Verifs(
                                networkname= playlist.id_zone_channel.networkname,
                                zonename= playlist.id_zone_channel.zonename,
                                broadcast_date= broadcast_date,
                                trafficId= adspot_in_avail.trafficid,
                                spotId= adspot_in_avail.id_adspot.adspot_name,
                                airTime= airTime.strftime("%Y-%m-%d %H:%M:%S"),
                                airLength= time.strftime("%H%M%S00", time.gmtime(int(adspot_in_avail.id_adspot.duration))),
                                airStatuscode= "0001" if remaining_duration_seconds >= adspot_in_avail.id_adspot.duration else "0008",
                                revision= playlist.version,
                                vercomplete = True
                            )
                            new_ad_verif.save()
                            remaining_duration_seconds -= adspot_in_avail.id_adspot.duration
                            airTime += timedelta(seconds=adspot_in_avail.id_adspot.duration)
                            # Append verif_spot to static_verifs
                            static_verifs.append(verif_spot)
            return JsonResponse(
                {
                    "playlist":{
                        "id": playlist.id_playlist,
                        "version": playlist.version,
                        "broadcast_date": broadcast_date,
                        "start_date": playlist.start_date,
                        "end_date": playlist.end_date,
                        "is_draft": playlist.is_draft,
                        "draft_version": playlist.draft_version,
                        "created_at": playlist.created_at,
                        "draft_version": playlist.draft_version,
                        "channel": {
                            "id": playlist.id_channel.id_channel,
                            "name": playlist.id_channel.channel_name,
                        },
                        "region": {
                            "id": playlist.id_zone_channel.id_zone_channel,
                            "region": playlist.id_zone_channel.region,
                            "zonename": playlist.id_zone_channel.zonename,
                            "networkname": playlist.id_zone_channel.networkname,
                        },
                    },
                    "verifs": static_verifs,
                    "status": "success",
                    "message": "Static verifications validation successful"
                }
            )
        else:
            return JsonResponse(
                {
                    "status": "Failed",
                    "message": "Playlist Not Found"
                }
            )


class VerifsStaticInsert(View):
    template_name = "verifs/index.html"

    def get(self, request):
        # Render the template with the current date included in the context
        return render(request, self.template_name, {})

    def post(self, request):

        if "verifs_file" in request.FILES:

            verifs_file = request.FILES["verifs_file"]

            if verifs_file.name.endswith(".ver"):
                #
                try:
                    import xml.etree.ElementTree as ET

                    # All operations in one line
                    last_part = os.path.splitext(verifs_file.name)[0].split('-')[-1]
                    #
                    tree = ET.parse(verifs_file)
                    root = tree.getroot()

                    results = []
                    namespace = {"ns": "http://www.scte.org/schemas/118-3/201X"}

                    for cue_message in root.findall("ns:CueMessage", namespace):
                        network_name = root.attrib.get("networkName")
                        zone_name = root.attrib.get("zoneName")

                        # Retrieve the channel zone information associated with the playlist's verifs file
                        channel_zone = ChannelsZone.objects.filter(
                            networkname=network_name,
                            verifs_number=last_part
                        ).first()

                        print(channel_zone)

                        broadcast_date = root.attrib.get("broadcast_date")

                        for spot in cue_message.findall("ns:Spot", namespace):
                            traffic_id = spot.attrib.get("trafficId")
                            spot_id = spot.attrib.get("spotId")
                            air_time = spot.attrib.get("airTime")
                            air_length = spot.attrib.get("airLength")
                            air_status_code = spot.attrib.get("airStatusCode")
                            revision = spot.attrib.get("revision")

                            results.append({
                                "networkname": channel_zone.id_channel.channel_name,
                                "zonename": channel_zone.id_zone_channel,
                                "broadcast_date": broadcast_date,
                                "trafficId": traffic_id,
                                "spotId": spot_id,
                                "airTime": air_time.replace('T', ' ').split('+')[0],
                                "airLength": air_length,
                                "airStatusCode": air_status_code,
                                "revision": revision
                            })

                            Verifs.objects.update_or_create(
                                networkname = channel_zone.id_channel.channel_name,
                                zonename = channel_zone.id_zone_channel,
                                broadcast_date = broadcast_date,
                                trafficId = traffic_id,
                                spotId = spot_id,
                                airTime = air_time.replace('T', ' ').split('+')[0],
                                airLength = air_length,
                                airStatuscode = air_status_code,
                                revision = revision,
                                vercomplete = "false"
                            )


                    return JsonResponse({"status": "Success", "message": "Verifs Collected successfully.", "result": results})
                except Exception as e:
                    print(e)
                    return JsonResponse({"status": "Failed", "message": str(e)})
            else:
                return JsonResponse({"status": "Failed", "message": "Please upload a valid Verifs file."})
        else:
            return JsonResponse({"status": "Failed", "message": "No file uploaded."})


@login_required
def generate_verifs(request):

    if request.method == "POST":
        import pandas as pd
        from django.db import connection
        cursor = connection.cursor()
        channels = request.POST.get('channels')
        adspots = request.POST.get('adspots')
        start_day = request.POST.get('start_day')
        end_day = request.POST.get('end_day')
        print(start_day)
        print(end_day)
        start_day = str(start_day).replace('-','')
        end_day = str(end_day).replace('-','')
        q = """
            select * from Verifs
            LEFT JOIN SFR_analytics on SUBSTRING(Verifs.airTime, 12, 5) = SUBSTRING(SFR_analytics.`minute`, 1, 5) and SFR_analytics.sfr_channel_name = '{}'
            where Verifs.spotId LIKE '%{}%' and Verifs.airStatusCode = '0001' and Verifs.broadcast_date > '{}' and Verifs.broadcast_date < '{}'
        """
        try :
            cursor.execute(q.format(channels,adspots,start_day,end_day))
            row = cursor.fetchall()
            print(row)
            df = pd.DataFrame(row)
            df2 = df[[0,12,14,3,4,5,6,7,8,15,16,17,18]]
            df2.columns = ['id_verifs','Channel','Region','broadcast_date','trafficId','spotId','airTime','airLenght','airStatus','cible','indicateur','minute','purcent']

            with BytesIO() as b:
                # Use the StringIO object as the filehandle.
                writer = pd.ExcelWriter(b, engine='xlsxwriter')
                df2.to_excel(writer,index = False)
                writer.save()
                # Set up the Http response.
                filename = start_day+'_'+adspots+'.xlsx'
                response = HttpResponse(
                    b.getvalue(),
                    content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                )
                response['Content-Disposition'] = 'attachment; filename=%s' % filename
                return response

        except :
            print("===================================================")
            print("===================================================")
            print("===================================================")

    channels = Channels.objects.filter(id_user = user)

    adspots = Adspots.objects.filter(id_channel__in = channels).values_list('adspot_name')
    adspots = [ads[0] for ads in adspots]
    channels = [ch.sfr_channel_name for ch in channels ]

    print(channels)
    return render(request,'core/generate_verifs.html',{'adspots':adspots , 'channels' : channels})

