from django.contrib import admin
from .models import UexistEntry, UexistEntriesTargets, UexistFiles, UexistTargets, Users, UexistFilesTargets,UexistEntriesMatched
from django.urls import path
from django.template.response import TemplateResponse
from django.core.paginator import Paginator
from django.db.models import OuterRef, Subquery,Count
from django.http import HttpResponse
from collections import defaultdict
from django.db.models import Sum
from django.utils import timezone
import csv

class CustomAdminSite(admin.AdminSite):
    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('custom-page/', self.admin_view(self.custom_page), name='custom-page'),
            path('download-page/', self.admin_view(self.download_page), name='download-page-all'),
            path('download-page/<int:file_id>/', self.admin_view(self.download_page), name='download-page'),
            path('stats/', self.admin_view(self.stats_page), name='stats'),
            path('leads/', self.admin_view(self.leads_page), name='leads-page'),
            path('datewise-leads/', self.admin_view(self.datewise_leads_page), name='datewise-leads-page')
        ]
        return custom_urls + urls
    
    def datewise_leads_page(self , request):
        today = timezone.now().date()
        selected_date = request.GET.get('date') or today.strftime('%Y-%m-%d')

        # Subquery to get the name of the matched_target
        target_subquery = UexistTargets.objects.filter(
            target_id=OuterRef('matched_target')
        ).values('name')[:1]

        # Annotate each entry with target name
        annotated_leads = UexistEntriesMatched.objects.filter(
            updated_date__date=selected_date
        ).annotate(
            target_name=Subquery(target_subquery)
        )

        # Group by target_name and count
        summary_data = annotated_leads.values('target_name').annotate(
            total=Count('entry_id')
        ).order_by('-total')

        context = dict(
            self.each_context(request),
            selected_date=selected_date,
            today=today.strftime('%Y-%m-%d'),
            summary_data=summary_data,
        )

        return TemplateResponse(request,"admin/datewise-leads-page.html",context)


    def leads_page(self, request):
        target_names = self.values()
        selected_source = request.GET.get('source')
        selected_date = request.GET.get('date')

        # Subquery to get the name of the matched_target
        target_subquery = UexistTargets.objects.filter(target_id=OuterRef('matched_target')).values('name')[:1]

        files = UexistEntriesMatched.objects.annotate(
        target_name=Subquery(target_subquery)
        )

        # Apply filter if a source is selected
        if selected_source:
            files = files.filter(target_name=selected_source)
        if selected_date:
            files = files.filter(updated_date__date = selected_date)
        
        files = files.order_by('-updated_date')
        files = files.values('firstname', 'lastname', 'email', 'phone', 'target_name', 'updated_date')

        # Paginate
        paginator = Paginator(files, 50)
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)
        
        context = dict(
            self.each_context(request),
            names=target_names,
            custom_data=page_obj,
            page_obj=page_obj

        )
        
        return TemplateResponse(request, "admin/leads_page.html", context)

    def stats_page(self, request):

        target_to_files = defaultdict(list)
        targets = UexistFilesTargets.objects.values('target_id', 'file_id', 'processed')

        processed_by_target = defaultdict(int)

        for row in targets:
            target_id = row['target_id']
            file_id = row['file_id']
            processed = row.get('processed', 0) or 0

            target_to_files[target_id].append(file_id)
            processed_by_target[target_id] += processed
        
        target_ids = list(target_to_files.keys())
        target_names = {
            t['target_id']: t['name']
            for t in UexistTargets.objects.filter(target_id__in=target_ids).values('target_id', 'name')
        }

        file_data = []

        for target_id, file_ids in target_to_files.items():
            result = {}
            total_processed = UexistFiles.objects.filter(file_id__in=file_ids).aggregate(
                total=Sum('total')
            )['total'] or 0
            result["file"] = target_id
            result["remaining"] = (total_processed - processed_by_target[target_id])
            result["name"] = target_names.get(target_id, "Unknown")
            file_data.append(result)

        context = dict(
            self.each_context(request),
            file_data=file_data,

        )

        return TemplateResponse(request, "admin/stats_page.html", context)

    def custom_page(self, request):
        target_names = self.values()
        custom_data = self.custom_block()
        total_match = UexistEntriesMatched.objects.count() 
        context = dict(
            self.each_context(request),
            names=target_names,
            file_data = custom_data,
            total_match_count=total_match

        )
        
        return TemplateResponse(request, "admin/custom_page.html", context)
    
    def download_page(self, request,file_id=None): 
        target_names = self.values()
        selected_source = request.GET.get('source')

        # Subquery to get the name of the matched_target
        target_subquery = UexistTargets.objects.filter(target_id=OuterRef('matched_target')).values('name')[:1]

        if file_id is None:
            files = UexistEntriesMatched.objects.annotate(
            target_name=Subquery(target_subquery)
            )
        else:
            # Start with all files with matched targets
            files = UexistEntry.objects.filter(file_id=file_id).exclude(matched_target__isnull=True).annotate(
            target_name=Subquery(target_subquery)
            )

        # Apply filter if a source is selected
        if selected_source:
            files = files.filter(target_name=selected_source)
        
        # Handle CSV download
        if request.GET.get("download") == "csv":
            response = HttpResponse(content_type='text/csv')
            response['Content-Disposition'] = 'attachment; filename="entries.csv"'

            writer = csv.writer(response)
            writer.writerow(['FIRSTNAME', 'LASTNAME', 'EMAIL', 'PHONE', 'SOURCES','UPDATED_DATE'])

            for file in files:
                writer.writerow([
                    file.firstname,
                    file.lastname,
                    file.email,
                    file.phone,
                    file.target_name,
                    file.updated_date
                ])

            return response

        # Select only the required fields
        files = files.values('firstname', 'lastname', 'email', 'phone', 'matched_target', 'target_name','updated_date')

        # Paginate
        paginator = Paginator(files, 50)
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)

        context = dict(
            self.each_context(request),
            names=target_names,
            custom_data=page_obj,
            page_obj=page_obj,
            file_id = file_id
        )
        return TemplateResponse(request, "admin/download_page.html", context)

   
    def values(self):
        all_values = list(UexistTargets.objects.filter(active=1).values_list('name', flat=True).distinct())
        print(all_values , "all_values")
        return all_values
    
    def download_page_block(self):
        files = UexistEntry.objects.exclude(matched_target__isnull=True)

        # print("files are",files)
        file_blocks = []

        for file in files:
            file_blocks.append({
                'first_name': file.firstname,
                'last_name':file.lastname,
                'email':file.email,
                'phone': file.phone,
                'sources': file.matched_target
            })
            # print("file block",file_blocks)
        return file_blocks

    def custom_block(self):
        files = UexistFiles.objects.all().order_by('-file_id')
        # print("files are",files)
        file_blocks = []

        for file in files:
            # Get all related rows from uexist_files_targets for this file
            file_targets = UexistFilesTargets.objects.filter(file_id=file.file_id)
            # print("file_target are",file_targets)
            # Prepare target list for this file
            target_data = []
            for ft in file_targets:
                try:
                    target_name = UexistTargets.objects.get(target_id=ft.target_id).name
                    matched_count = UexistEntriesMatched.objects.filter(
                    file_id=file.file_id , matched_target=ft.target_id).count()
                    # print("target name",target_name)
                except UexistTargets.DoesNotExist:
                    target_name = "Unknown"

                target_data.append({
                    'name': target_name,
                    'processed': ft.processed,
                    'matched_count':matched_count
                })


            # Append complete block
            file_blocks.append({
                'file_id':file.file_id,
                'file_name': file.file,
                'ready':file.ready,
                'loaded':file.loaded,
                'total': file.total,
                'targets': target_data,
                'uploaded_date':file.date
            })
            # print("file block",file_blocks)
        return file_blocks
    
# Replace default admin site
custom_admin_site = CustomAdminSite(name='custom_admin')


# Register your models here.
admin.site.register(UexistEntry)
admin.site.register(UexistEntriesTargets)
admin.site.register(UexistFiles)
admin.site.register(UexistTargets)
admin.site.register(UexistFilesTargets)
admin.site.register(Users)