# reports/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import TemplateView, ListView, DetailView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.http import HttpResponse, JsonResponse, FileResponse
from django.db.models import Count, Sum, Avg, Q
from django.utils import timezone
from datetime import date, timedelta, datetime
import csv
import io

from students.models import Student
from academics.models import SchoolClass, Attendance, Subject
from finance.models import Invoice, Payment, Expense, ExpenseCategory
from staff.models import Staff

# ========== ACADEMIC REPORTS ==========

class AcademicReportView(LoginRequiredMixin, TemplateView):
    """Academic reports dashboard"""
    template_name = 'reports/academic.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['classes'] = SchoolClass.objects.all()
        context['terms'] = [1, 2, 3]
        context['years'] = range(2020, date.today().year + 2)
        return context

class ClassReportView(LoginRequiredMixin, TemplateView):
    """Generate class report"""
    template_name = 'reports/class_report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        class_id = self.kwargs.get('class_id')
        term = self.request.GET.get('term', 1)
        year = self.request.GET.get('year', date.today().year)
        
        school_class = SchoolClass.objects.get(id=class_id)
        students = Student.objects.filter(current_class=school_class).order_by('first_name')
        
        context['class'] = school_class
        context['students'] = students
        context['term'] = term
        context['year'] = year
        
        # Get attendance statistics for each student
        student_stats = []
        for student in students:
            attendances = Attendance.objects.filter(
                student=student,
                date__year=year
            )
            
            total = attendances.count()
            present = attendances.filter(status='present').count()
            
            student_stats.append({
                'student': student,
                'total_days': total,
                'present': present,
                'absent': attendances.filter(status='absent').count(),
                'late': attendances.filter(status='late').count(),
                'attendance_rate': round((present / total) * 100, 1) if total > 0 else 0
            })
        
        context['student_stats'] = student_stats
        
        return context

class StudentReportView(LoginRequiredMixin, DetailView):
    """Generate individual student report"""
    model = Student
    template_name = 'reports/student_report.html'
    context_object_name = 'student'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        term = self.request.GET.get('term', 1)
        year = self.request.GET.get('year', date.today().year)
        
        # Attendance for the period
        attendances = Attendance.objects.filter(
            student=self.object,
            date__year=year
        )
        
        total = attendances.count()
        present = attendances.filter(status='present').count()
        
        context['attendance'] = {
            'total': total,
            'present': present,
            'absent': attendances.filter(status='absent').count(),
            'late': attendances.filter(status='late').count(),
            'rate': round((present / total) * 100, 1) if total > 0 else 0
        }
        
        # Fee summary
        invoices = Invoice.objects.filter(student=self.object)
        total_invoiced = invoices.aggregate(Sum('total_amount'))['total_amount__sum'] or 0
        total_paid = Payment.objects.filter(
            student=self.object,
            status='completed'
        ).aggregate(Sum('amount'))['amount__sum'] or 0
        
        context['fees'] = {
            'invoiced': total_invoiced,
            'paid': total_paid,
            'balance': total_invoiced - total_paid
        }
        
        context['term'] = term
        context['year'] = year
        
        return context

def generate_academic_report(request):
    """Generate and download academic report"""
    if request.method == 'POST':
        report_type = request.POST.get('report_type')
        class_id = request.POST.get('class_id')
        term = request.POST.get('term')
        year = request.POST.get('year')
        
        # Create CSV response
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = f'attachment; filename="academic_report_{year}_term{term}.csv"'
        
        writer = csv.writer(response)
        
        if report_type == 'class' and class_id:
            school_class = SchoolClass.objects.get(id=class_id)
            students = Student.objects.filter(current_class=school_class)
            
            writer.writerow(['Student ID', 'Name', 'Attendance %', 'Status'])
            
            for student in students:
                # Calculate attendance
                attendances = Attendance.objects.filter(
                    student=student,
                    date__year=year
                )
                total = attendances.count()
                present = attendances.filter(status='present').count()
                rate = round((present / total) * 100, 1) if total > 0 else 0
                
                writer.writerow([
                    student.student_id,
                    student.get_full_name(),
                    rate,
                    student.status
                ])
        
        messages.success(request, 'Report generated successfully!')
        return response
    
    return redirect('reports:academic_report')

# ========== ATTENDANCE REPORTS ==========

class AttendanceReportView(LoginRequiredMixin, TemplateView):
    """Attendance reports"""
    template_name = 'reports/attendance_report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        from_date = self.request.GET.get('from_date')
        to_date = self.request.GET.get('to_date')
        class_id = self.request.GET.get('class')
        
        if not from_date:
            from_date = date.today().replace(day=1)
        if not to_date:
            to_date = date.today()
        
        context['from_date'] = from_date
        context['to_date'] = to_date
        context['classes'] = SchoolClass.objects.all()
        
        # Build statistics
        classes = SchoolClass.objects.all()
        if class_id:
            classes = classes.filter(id=class_id)
        
        stats = []
        for cls in classes:
            attendances = Attendance.objects.filter(
                school_class=cls,
                date__gte=from_date,
                date__lte=to_date
            )
            
            total = attendances.count()
            if total > 0:
                present = attendances.filter(status='present').count()
                stats.append({
                    'class': cls.name,
                    'class_id': cls.id,
                    'total': total,
                    'present': present,
                    'absent': attendances.filter(status='absent').count(),
                    'late': attendances.filter(status='late').count(),
                    'rate': round((present / total) * 100, 1)
                })
        
        context['stats'] = stats
        
        # Overall statistics
        all_attendances = Attendance.objects.filter(
            date__gte=from_date,
            date__lte=to_date
        )
        total_all = all_attendances.count()
        if total_all > 0:
            context['overall_rate'] = round(
                (all_attendances.filter(status='present').count() / total_all) * 100, 1
            )
        
        return context

class ClassAttendanceReportView(LoginRequiredMixin, TemplateView):
    """Attendance report for a specific class"""
    template_name = 'reports/class_attendance_report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        class_id = self.kwargs.get('class_id')
        month = self.request.GET.get('month', date.today().month)
        year = self.request.GET.get('year', date.today().year)
        
        school_class = SchoolClass.objects.get(id=class_id)
        students = Student.objects.filter(current_class=school_class)
        
        # Get all days in the month
        start_date = date(int(year), int(month), 1)
        if month == 12:
            end_date = date(int(year) + 1, 1, 1) - timedelta(days=1)
        else:
            end_date = date(int(year), int(month) + 1, 1) - timedelta(days=1)
        
        days = [start_date + timedelta(days=i) for i in range((end_date - start_date).days + 1)]
        
        # Get attendance for each student
        today = date.today()
        attendance_data = []
        for student in students:
            student_attendance = []
            for day in days:
                is_weekend = day.weekday() >= 5          # Saturday=5, Sunday=6
                is_future  = day > today

                att = Attendance.objects.filter(
                    student=student,
                    date=day
                ).first()

                if att:
                    status = att.status
                elif is_weekend:
                    status = 'weekend'
                elif is_future:
                    status = 'future'
                else:
                    status = 'no_record'   # school day with no entry taken yet

                student_attendance.append({
                    'date': day,
                    'status': status,
                    'is_weekend': is_weekend,
                    'is_future': is_future,
                })

            attendance_data.append({
                'student': student,
                'attendance': student_attendance
            })
        
        context['class'] = school_class
        context['attendance_data'] = attendance_data
        context['days'] = days
        context['month'] = int(month)
        context['year'] = int(year)
        context['months'] = [
            (1,'January'),(2,'February'),(3,'March'),(4,'April'),
            (5,'May'),(6,'June'),(7,'July'),(8,'August'),
            (9,'September'),(10,'October'),(11,'November'),(12,'December'),
        ]
        
        return context

def export_attendance_report(request):
    """Export attendance report as CSV"""
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="attendance_report.csv"'
    
    writer = csv.writer(response)
    writer.writerow(['Date', 'Class', 'Student', 'Status', 'Remarks'])
    
    from_date = request.GET.get('from_date')
    to_date = request.GET.get('to_date')
    
    attendances = Attendance.objects.filter(
        date__gte=from_date,
        date__lte=to_date
    ).select_related('student', 'school_class')
    
    for att in attendances:
        writer.writerow([
            att.date,
            att.school_class.name,
            str(att.student),
            att.get_status_display(),
            att.remarks
        ])
    
    return response

# ========== FINANCIAL REPORTS ==========

class FinancialReportView(LoginRequiredMixin, TemplateView):
    """Financial reports dashboard"""
    template_name = 'reports/financial_report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        from_date = self.request.GET.get('from_date')
        to_date = self.request.GET.get('to_date')
        
        if not from_date:
            from_date = date.today().replace(day=1)
        if not to_date:
            to_date = date.today()
        
        context['from_date'] = from_date
        context['to_date'] = to_date
        
        # Revenue
        payments = Payment.objects.filter(
            status='completed',
            payment_date__gte=from_date,
            payment_date__lte=to_date
        )
        context['total_revenue'] = payments.aggregate(Sum('amount'))['amount__sum'] or 0
        
        # Expenses
        expenses = Expense.objects.filter(
            expense_date__gte=from_date,
            expense_date__lte=to_date
        )
        context['total_expenses'] = expenses.aggregate(Sum('amount'))['amount__sum'] or 0
        
        context['net_profit'] = context['total_revenue'] - context['total_expenses']
        
        # Revenue by payment method
        by_method = []
        for method_code, method_name in Payment.PAYMENT_METHOD_CHOICES:
            total = payments.filter(payment_method=method_code).aggregate(Sum('amount'))['amount__sum'] or 0
            if total > 0:
                by_method.append({
                    'method': method_name,
                    'total': total
                })
        context['by_method'] = by_method
        
        # Expenses by category
        by_category = []
        for category in ExpenseCategory.objects.all():
            total = expenses.filter(category=category).aggregate(Sum('amount'))['amount__sum'] or 0
            if total > 0:
                by_category.append({
                    'category': category.name,
                    'total': total
                })
        context['by_category'] = by_category
        
        return context

class TermFinancialReportView(LoginRequiredMixin, TemplateView):
    """Financial report for a specific term"""
    template_name = 'reports/term_financial_report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        term = self.kwargs.get('term')
        year = self.request.GET.get('year', date.today().year)
        
        # Define term dates (you'd need to configure these)
        term_dates = {
            1: {'start': f'{year}-09-01', 'end': f'{year}-12-20'},
            2: {'start': f'{year+1}-01-10', 'end': f'{year+1}-03-30'},
            3: {'start': f'{year+1}-04-15', 'end': f'{year+1}-07-15'},
        }
        
        start_date = term_dates[term]['start']
        end_date = term_dates[term]['end']
        
        context['term'] = term
        context['year'] = year
        context['start_date'] = start_date
        context['end_date'] = end_date
        
        # Get data for this term
        invoices = Invoice.objects.filter(
            academic_year=f"{year}-{year+1}",
            term=term
        )
        
        context['total_invoiced'] = invoices.aggregate(Sum('total_amount'))['total_amount__sum'] or 0
        context['total_collected'] = invoices.aggregate(Sum('amount_paid'))['amount_paid__sum'] or 0
        context['outstanding'] = context['total_invoiced'] - context['total_collected']
        
        return context

class YearlyFinancialReportView(LoginRequiredMixin, TemplateView):
    """Yearly financial report"""
    template_name = 'reports/yearly_financial_report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        year = self.kwargs.get('year')
        
        context['year'] = year
        
        # Monthly breakdown
        monthly_data = []
        for month in range(1, 13):
            start_date = date(int(year), month, 1)
            if month == 12:
                end_date = date(int(year) + 1, 1, 1) - timedelta(days=1)
            else:
                end_date = date(int(year), month + 1, 1) - timedelta(days=1)
            
            revenue = Payment.objects.filter(
                status='completed',
                payment_date__gte=start_date,
                payment_date__lte=end_date
            ).aggregate(Sum('amount'))['amount__sum'] or 0
            
            expenses = Expense.objects.filter(
                expense_date__gte=start_date,
                expense_date__lte=end_date
            ).aggregate(Sum('amount'))['amount__sum'] or 0
            
            monthly_data.append({
                'month': start_date.strftime('%B'),
                'revenue': revenue,
                'expenses': expenses,
                'profit': revenue - expenses
            })
        
        context['monthly_data'] = monthly_data
        
        # Yearly totals
        context['total_revenue'] = sum(m['revenue'] for m in monthly_data)
        context['total_expenses'] = sum(m['expenses'] for m in monthly_data)
        context['total_profit'] = context['total_revenue'] - context['total_expenses']
        
        return context

def export_financial_report(request):
    """Export financial report as CSV"""
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="financial_report.csv"'
    
    writer = csv.writer(response)
    writer.writerow(['Date', 'Type', 'Description', 'Amount', 'Category'])
    
    from_date = request.GET.get('from_date')
    to_date = request.GET.get('to_date')
    
    # Payments (revenue)
    payments = Payment.objects.filter(
        status='completed',
        payment_date__gte=from_date,
        payment_date__lte=to_date
    ).select_related('student')
    
    for payment in payments:
        writer.writerow([
            payment.payment_date,
            'Revenue',
            f"Payment from {payment.student}",
            payment.amount,
            payment.get_payment_method_display()
        ])
    
    # Expenses
    expenses = Expense.objects.filter(
        expense_date__gte=from_date,
        expense_date__lte=to_date
    ).select_related('category')
    
    for expense in expenses:
        writer.writerow([
            expense.expense_date,
            'Expense',
            expense.description,
            -expense.amount,
            expense.category.name
        ])
    
    return response

# ========== CUSTOM REPORTS ==========

class CustomReportView(LoginRequiredMixin, TemplateView):
    """Custom report builder"""
    template_name = 'reports/custom_report.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        context['data_sources'] = [
            {'id': 'students', 'name': 'Students'},
            {'id': 'attendance', 'name': 'Attendance'},
            {'id': 'payments', 'name': 'Payments'},
            {'id': 'invoices', 'name': 'Invoices'},
            {'id': 'expenses', 'name': 'Expenses'},
        ]
        
        return context

def generate_custom_report(request):
    """Generate custom report based on selected criteria"""
    if request.method == 'POST':
        data_source = request.POST.get('data_source')
        fields = request.POST.getlist('fields')
        filters = request.POST.get('filters')
        
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = f'attachment; filename="custom_report_{data_source}.csv"'
        
        writer = csv.writer(response)
        
        if data_source == 'students':
            writer.writerow(['ID', 'Name', 'Class', 'Status'])
            for student in Student.objects.all():
                writer.writerow([
                    student.student_id,
                    student.get_full_name(),
                    student.current_class.name if student.current_class else '',
                    student.status
                ])
        
        elif data_source == 'attendance':
            writer.writerow(['Date', 'Student', 'Class', 'Status'])
            for att in Attendance.objects.all().select_related('student', 'school_class')[:1000]:
                writer.writerow([
                    att.date,
                    str(att.student),
                    att.school_class.name,
                    att.get_status_display()
                ])
        
        return response
    
    return redirect('reports:custom_report')

# ========== PDF EXPORT FUNCTIONS (ADD THESE) ==========

def export_report_pdf(request, report_type, report_id):
    """Export report as PDF (placeholder)"""
    # This is a placeholder function
    # In a real application, you would use a library like WeasyPrint or ReportLab
    from django.http import HttpResponse
    from django.template.loader import get_template
    
    # For now, return a simple message
    html = f"<html><body><h1>{report_type} Report {report_id}</h1><p>PDF export coming soon!</p></body></html>"
    
    # In production, you would convert this HTML to PDF
    # from xhtml2pdf import pisa
    # result = io.BytesIO()
    # pdf = pisa.pisaDocument(io.BytesIO(html.encode("UTF-8")), result)
    
    return HttpResponse(html)

def export_report_excel(request, report_type, report_id):
    """Export report as Excel (placeholder)"""
    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = f'attachment; filename="{report_type}_report_{report_id}.xls"'
    
    writer = csv.writer(response)
    writer.writerow(['Report Type', 'Report ID', 'Generated Date'])
    writer.writerow([report_type, report_id, date.today()])
    
    return response