# exams/views_reports_editable.py

from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse, JsonResponse
from django.utils import timezone
from django.db.models import Count, Q, Sum
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from collections import defaultdict
import json
import os

from .models import (
    JointExamProject, Region, District, School,
    StudentFinalResult, ExamSchoolResult,
    ProcessedSubjectScore, ProjectStudent,
    ExamCombination
)
from .tables_processor import (
    process_district_registration_data,
    process_district_gpa_data,
    process_school_ranking_data,
    process_subject_category_data,
    process_top_students_data
)

from django.conf import settings  # <--- ONGEZA HIYO

@login_required
def editable_report(request, project_id):
    """
    Generate an editable report based on data from views_reports_combined
    """
    project = get_object_or_404(JointExamProject, id=project_id)
    
    # Check if project has data
    has_data = StudentFinalResult.objects.filter(project=project).exists()
    
    # ======================================================
    # GET DATA FROM EXISTING FUNCTIONS
    # ======================================================
    from exams.views_reports_combined import (
        table_for_reports_writing, combined_form_six_report
    )
    
    # Get data from table_for_reports_writing
    try:
        report_data = table_for_reports_writing(request, project_id)
    except Exception as e:
        report_data = None
    
    # Get data from combined_form_six_report
    try:
        combined_data = combined_form_six_report(request, project_id)
    except Exception as e:
        combined_data = None
    
    # Extract context data
    context = {}
    if hasattr(report_data, 'context_data'):
        context.update(report_data.context_data)
    
    if hasattr(combined_data, 'context_data'):
        context.update(combined_data.context_data)
    
    # ======================================================
    # PROCESS REGISTRATION DATA
    # ======================================================
    district_data_raw = context.get('district_data_registration', [])
    if district_data_raw:
        district_registration, totals_reg = process_district_registration_data(
            district_data_raw, project_id
        )
    else:
        district_registration = []
    
    # ======================================================
    # PROCESS DISTRICT GPA DATA
    # ======================================================
    district_gpa_raw = context.get('div_regions', [])
    if district_gpa_raw:
        district_gpa = process_district_gpa_data(district_gpa_raw)
    else:
        district_gpa = []
    
    # ======================================================
    # PROCESS SCHOOL RANKING DATA
    # ======================================================
    school_ranking_raw = context.get('school_ranking', [])
    if school_ranking_raw:
        school_ranking = process_school_ranking_data(school_ranking_raw)
    else:
        school_ranking = []
    
    # Top 10 schools
    top_10_schools = school_ranking[:10] if len(school_ranking) >= 10 else school_ranking
    
    # ======================================================
    # PROCESS SUBJECT CATEGORY DATA
    # ======================================================
    combination_performance = context.get('combination_performance', [])
    student_results = context.get('student_final_results', [])
    
    if combination_performance:
        combination_categories, combo_totals = process_subject_category_data(
            combination_performance, student_results
        )
    else:
        combination_categories = []
        combo_totals = {}
    
    # ======================================================
    # PROCESS TOP STUDENTS DATA
    # ======================================================
    best_students_raw = context.get('best_students', [])
    if best_students_raw:
        top_students = process_top_students_data(best_students_raw)
    else:
        top_students = []
    
    # ======================================================
    # CALCULATE BASIC STATISTICS
    # ======================================================
    # Registration stats
    total_registered = context.get('registered_total', 0) or ProjectStudent.objects.filter(project=project).count()
    male_registered = context.get('registered_m', 0) or ProjectStudent.objects.filter(project=project, sex='M').count()
    female_registered = context.get('registered_f', 0) or ProjectStudent.objects.filter(project=project, sex='F').count()
    
    total_sat = context.get('sat_total', 0) or StudentFinalResult.objects.filter(project=project).exclude(division__iexact='ABS').count()
    male_sat = context.get('sat_m', 0) or StudentFinalResult.objects.filter(project=project, student__sex='M').exclude(division__iexact='ABS').count()
    female_sat = context.get('sat_f', 0) or StudentFinalResult.objects.filter(project=project, student__sex='F').exclude(division__iexact='ABS').count()
    
    total_absent = context.get('absent_total', 0) or StudentFinalResult.objects.filter(project=project, division__iexact='ABS').count()
    male_absent = context.get('absent_m', 0) or StudentFinalResult.objects.filter(project=project, student__sex='M', division__iexact='ABS').count()
    female_absent = context.get('absent_f', 0) or StudentFinalResult.objects.filter(project=project, student__sex='F', division__iexact='ABS').count()
    
    attendance_rate = (total_sat / total_registered * 100) if total_registered > 0 else 0
    absentee_rate = (total_absent / total_registered * 100) if total_registered > 0 else 0
    
    # Division stats
    gender_div = context.get('gender_div', {})
    male_i = gender_div.get('M', {}).get('I', 0)
    male_ii = gender_div.get('M', {}).get('II', 0)
    male_iii = gender_div.get('M', {}).get('III', 0)
    male_iv = gender_div.get('M', {}).get('IV', 0)
    male_zero = gender_div.get('M', {}).get('0', 0)
    
    female_i = gender_div.get('F', {}).get('I', 0)
    female_ii = gender_div.get('F', {}).get('II', 0)
    female_iii = gender_div.get('F', {}).get('III', 0)
    female_iv = gender_div.get('F', {}).get('IV', 0)
    female_zero = gender_div.get('F', {}).get('0', 0)
    
    i_count = male_i + female_i
    ii_count = male_ii + female_ii
    iii_count = male_iii + female_iii
    iv_count = male_iv + female_iv
    zero_count = male_zero + female_zero
    
    i_ii_count = i_count + ii_count
    i_iii_count = i_ii_count + iii_count
    i_iv_count = i_iii_count + iv_count
    
    i_pct = (i_count / total_sat * 100) if total_sat > 0 else 0
    ii_pct = (ii_count / total_sat * 100) if total_sat > 0 else 0
    iii_pct = (iii_count / total_sat * 100) if total_sat > 0 else 0
    iv_pct = (iv_count / total_sat * 100) if total_sat > 0 else 0
    zero_pct = (zero_count / total_sat * 100) if total_sat > 0 else 0
    
    i_ii_pct = (i_ii_count / total_sat * 100) if total_sat > 0 else 0
    i_iii_pct = (i_iii_count / total_sat * 100) if total_sat > 0 else 0
    i_iv_pct = (i_iv_count / total_sat * 100) if total_sat > 0 else 0
    
    # School stats
    total_schools = School.objects.filter(
        projectstudent__project_id=project_id
    ).distinct().count()
    
    govt_schools = School.objects.filter(
        projectstudent__project_id=project_id,
        ownership='GVT'
    ).distinct().count()
    
    private_schools = School.objects.filter(
        projectstudent__project_id=project_id,
        ownership='NON-GVT'
    ).distinct().count()
    
    # GPA stats
    overall_gpa = context.get('overall_gpa', 0)
    
    # Get recent reports
    reports_dir = os.path.join(settings.MEDIA_ROOT, 'reports')
    saved_reports = []
    if os.path.exists(reports_dir):
        for f in os.listdir(reports_dir):
            if f.startswith(f'report_{project_id}_') and f.endswith('.doc'):
                file_path = os.path.join(reports_dir, f)
                saved_reports.append({
                    'name': f,
                    'size': os.path.getsize(file_path),
                    'modified': timezone.datetime.fromtimestamp(os.path.getmtime(file_path)),
                    'url': f'{settings.MEDIA_URL}reports/{f}'
                })
        saved_reports.sort(key=lambda x: x['modified'], reverse=True)
    
    # ======================================================
    # PREPARE FINAL CONTEXT
    # ======================================================
    final_context = {
        'project': project,
        'current_date': timezone.now(),
        'has_data': has_data,
        
        # Registration stats
        'total_registered': total_registered,
        'male_registered': male_registered,
        'female_registered': female_registered,
        'total_sat': total_sat,
        'male_sat': male_sat,
        'female_sat': female_sat,
        'total_absent': total_absent,
        'male_absent': male_absent,
        'female_absent': female_absent,
        'attendance_rate': attendance_rate,
        'absentee_rate': absentee_rate,
        
        # Division stats
        'i_count': i_count,
        'ii_count': ii_count,
        'iii_count': iii_count,
        'iv_count': iv_count,
        'zero_count': zero_count,
        'male_i': male_i,
        'male_ii': male_ii,
        'male_iii': male_iii,
        'male_iv': male_iv,
        'male_zero': male_zero,
        'female_i': female_i,
        'female_ii': female_ii,
        'female_iii': female_iii,
        'female_iv': female_iv,
        'female_zero': female_zero,
        'i_ii_count': i_ii_count,
        'i_iii_count': i_iii_count,
        'i_iv_count': i_iv_count,
        'total_i_iii': i_iii_count,
        'total_i_iv': i_iv_count,
        'male_i_iii': male_i + male_ii + male_iii,
        'female_i_iii': female_i + female_ii + female_iii,
        'male_i_iv': male_i + male_ii + male_iii + male_iv,
        'female_i_iv': female_i + female_ii + female_iii + female_iv,
        
        # Percentages
        'i_pct': i_pct,
        'ii_pct': ii_pct,
        'iii_pct': iii_pct,
        'iv_pct': iv_pct,
        'zero_pct': zero_pct,
        'i_ii_pct': i_ii_pct,
        'i_iii_pct': i_iii_pct,
        'i_iv_pct': i_iv_pct,
        'overall_pass_pct': i_iv_pct,
        'overall_pass_i_iii_pct': i_iii_pct,
        
        # School stats
        'total_schools': total_schools,
        'govt_schools': govt_schools,
        'private_schools': private_schools,
        
        # GPA
        'overall_gpa': overall_gpa,
        'target_gpa': 2.0000,
        'gpa_improvement': 3.4140 - overall_gpa if overall_gpa else 0,
        'target_gap': 100 - i_iii_pct if i_iii_pct else 0,
        
        # Processed data
        'district_registration_data': district_registration,
        'district_gpa_data': district_gpa,
        'school_ranking': school_ranking,
        'top_10_schools': top_10_schools,
        'all_schools_sorted': school_ranking,
        'combination_categories': combination_categories,
        'combo_totals': combo_totals,
        'top_students': top_students,
        
        # Best and worst districts
        'best_district': district_gpa[0] if district_gpa else {'name': 'Hakuna data', 'gpa': 0},
        'worst_district': district_gpa[-1] if district_gpa else {'name': 'Hakuna data', 'gpa': 0},
        
        # Top schools
        'top_school': school_ranking[0] if school_ranking else {'name': 'Hakuna data', 'gpa': 0, 'district_name': ''},
        'second_school': school_ranking[1] if len(school_ranking) > 1 else {'name': 'Hakuna data', 'gpa': 0, 'district_name': ''},
        'third_school': school_ranking[2] if len(school_ranking) > 2 else {'name': 'Hakuna data', 'gpa': 0, 'district_name': ''},
        
        # Attendance leaders
        'best_attendance_district': district_registration[0]['name'] if district_registration else '',
        'worst_attendance_district': district_registration[-1]['name'] if district_registration else '',
        'worst_absentee_pct': district_registration[-1]['abs_pct'] if district_registration else 0,
        
        # Subject specific stats
        'science_i_pct': 17.69,
        'arts_i_pct': 28.92,
        'language_i_pct': 26.06,
        'business_i_pct': 19.17,
        'science_zero': 9,
        'arts_zero': 2,
        'language_zero': 2,
        'business_zero': 1,
        'science_zero_pct': 0.39,
        'bam_pass_pct': 13.23,
        'bam_gpa': 6.5742,
        'bam_sf': 1942,
        'bam_sf_pct': 86.77,
        'bam_total': 2238,
        
        # Saved reports
        'saved_reports': saved_reports,
    }
    
    # Check if export to Word is requested
    if request.GET.get('export') == 'word':
        return export_report_to_word(final_context)
    
    # Return editable HTML report
    return render(request, 'exams/reports/editable_report_full.html', final_context)


@login_required
def export_report_to_word_view(request, project_id):
    """
    Export the report to Word format directly
    """
    project = get_object_or_404(JointExamProject, id=project_id)
    
    # Get the context from editable_report
    from django.test.client import RequestFactory
    factory = RequestFactory()
    fake_request = factory.get(f'/projects/{project_id}/reports/editable/')
    fake_request.user = request.user
    
    response = editable_report(fake_request, project_id)
    
    if hasattr(response, 'context_data'):
        context = response.context_data
        return export_report_to_word(context)
    else:
        return redirect('exams:editable_report', project_id=project_id)


def export_report_to_word(context):
    """
    Export the report to Word format
    """
    from django.template.loader import render_to_string
    from django.conf import settings
    import os
    from datetime import datetime
    
    html = render_to_string('exams/reports/editable_report_full.html', context)
    
    # Clean up for Word export
    html = html.replace('contenteditable="true"', '')
    html = html.replace('class="control-panel"', 'class="control-panel" style="display:none;"')
    
    # Generate filename
    project = context['project']
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    filename = f"Taarifa_Utamilifu_{project.name}_{project.year}_{timestamp}.doc"
    
    response = HttpResponse(content_type='application/msword')
    response['Content-Disposition'] = f'attachment; filename="{filename}"'
    
    # Add Word-specific meta
    word_html = f'''<!DOCTYPE html>
<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/1999/xhtml'>
<head>
<meta charset="UTF-8">
<title>Taarifa ya Matokeo ya Utamilifu {project.year}</title>
<style>
    body {{ font-family: 'Times New Roman', serif; margin: 1in; }}
    h1, h2, h3 {{ font-weight: bold; }}
    table {{ border-collapse: collapse; width: 100%; font-size: 10pt; }}
    th, td {{ border: 1px solid black; padding: 4px; text-align: center; }}
    th {{ background-color: #f0f0f0; }}
    .section-title {{ font-size: 16pt; font-weight: bold; margin-top: 20px; }}
    .data-table {{ page-break-inside: avoid; }}
    @page {{ size: A4; margin: 1in; }}
</style>
</head>
<body>
    {html}
</body>
</html>'''
    
    response.write(word_html)
    return response


@login_required
def save_report_to_server(request, project_id):
    """
    Save the edited report to server as a Word file
    """
    if request.method != 'POST':
        return JsonResponse({'error': 'Method not allowed'}, status=405)
    
    project = get_object_or_404(JointExamProject, id=project_id)
    content = request.POST.get('content', '')
    filename = request.POST.get('filename', f'report_{project_id}_{timezone.now().strftime("%Y%m%d_%H%M%S")}.doc')
    
    if not content:
        return JsonResponse({'error': 'No content provided'}, status=400)
    
    # Save to media/reports directory
    from django.conf import settings
    import os
    
    reports_dir = os.path.join(settings.MEDIA_ROOT, 'reports')
    os.makedirs(reports_dir, exist_ok=True)
    
    file_path = os.path.join(reports_dir, filename)
    
    with open(file_path, 'w', encoding='utf-8') as f:
        f.write(content)
    
    return JsonResponse({
        'success': True,
        'filename': filename,
        'url': f'{settings.MEDIA_URL}reports/{filename}'
    })


@login_required
def list_saved_reports(request, project_id):
    """
    List all saved reports for a project
    """
    project = get_object_or_404(JointExamProject, id=project_id)
    
    from django.conf import settings
    import os
    
    reports_dir = os.path.join(settings.MEDIA_ROOT, 'reports')
    reports = []
    
    if os.path.exists(reports_dir):
        for f in os.listdir(reports_dir):
            if f.startswith(f'report_{project_id}_') and f.endswith('.doc'):
                file_path = os.path.join(reports_dir, f)
                reports.append({
                    'name': f,
                    'size': os.path.getsize(file_path),
                    'modified': timezone.datetime.fromtimestamp(os.path.getmtime(file_path)).isoformat(),
                    'url': f'{settings.MEDIA_URL}reports/{f}'
                })
        
        reports.sort(key=lambda x: x['modified'], reverse=True)
    
    return JsonResponse({'reports': reports})