# G:\routine\routineapi\routine\utils.py

from django import db
from django.http import HttpResponse
from django.template.loader import render_to_string
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from io import BytesIO
from django.shortcuts import get_object_or_404
from rest_framework import status
from rest_framework.response import Response

from routine.models import Routine
from routine.serializers import RoutineListSerializer
from timeslot.models import TimeSlot
from days.models import Day # Import Day model

def generate_routine_pdf(routine_slug):
    try:
        routine = get_object_or_404(Routine, slug=routine_slug)
    except Exception:
        return Response({'error': 'Routine not found'}, status=status.HTTP_404_NOT_FOUND)

    # Fetch related data for the routine
    serializer = RoutineListSerializer(routine)
    routine_data_for_template_raw = serializer.data
    # Fetch days and timeslots from DB
    all_days_db = Day.objects.select_related('status').all()
    all_timeslots_db = TimeSlot.objects.select_related('status').all().order_by('start_time')

    template_routine_data = {
        'department': routine_data_for_template_raw['department'],
        'year': routine_data_for_template_raw['year'],
        'batch': routine_data_for_template_raw['batch'],
        'semester': routine_data_for_template_raw['semester'],
        'name': routine_data_for_template_raw['name'],
        'routine_year': routine_data_for_template_raw['routine_year'],
        'effective_from': routine_data_for_template_raw['effective_from'],
        'all_teachers': routine_data_for_template_raw['all_teachers'],
        'all_courses': routine_data_for_template_raw['all_courses'],
        'days': []
    }

    # Prepare timeslots
    timeslots = [{
        'slot_name': ts.slot_name,
        'start_time': ts.start_time.strftime('%H:%M'),
        'end_time': ts.end_time.strftime('%H:%M'),
        'id': ts.id,
        'status': {'title': ts.status.title, 'slug': ts.status.slug} if ts.status else {'title': "Available", 'slug': "available"},
    } for ts in all_timeslots_db]

    # Day and slot construction logic (re-used from original)
    for day_obj in all_days_db:
        day_slots = []
        for timeslot_obj in all_timeslots_db:
            entry = next((
                rd for rd in routine_data_for_template_raw['routine_data']
                if rd.get('timeslot') and int(rd['timeslot'].get('id')) == timeslot_obj.id and 
                   rd.get('day') and int(rd['day'].get('id')) == day_obj.id
            ), None)

            course = entry['course'] if entry else None
            teacher = entry['teacher'] if entry else None
            room = entry['room'] if entry else None
            
            slot_type = "empty"
            content = ""
            if entry and entry['status']['slug'] != 'hidden-routine_data':
                slot_type = "Available"
            elif timeslot_obj.status and 'break-time_slot' in timeslot_obj.status.slug:
                slot_type = "break"
                content = timeslot_obj.slot_name

            day_slots.append({
                'type': slot_type,
                'content': content,
                'course': {'code': course['course_code']} if course else None,
                'teacher': {'code': teacher['teacher_code']} if teacher else None,
                'room': {'room_number': room['room_number']} if room else None,
                'colspan': int(float(course['credit_hours'])) if course and course['credit_hours'] else 1,
            })
        
        final_day_slots = []
        i = 0
        while i < len(day_slots):
            current_slot = day_slots[i]
            colspan = current_slot['colspan'] if current_slot['type'] == 'Available' else 1
            final_day_slots.append(current_slot)
            if colspan > 1:
                for j in range(1, colspan):
                    if i + j < len(day_slots):
                        if day_slots[i+j]['type'] != 'break':
                            day_slots[i+j]['type'] = 'hidden'
                            final_day_slots.append(day_slots[i+j])
                        else:
                            current_slot['colspan'] = j
                            final_day_slots.append(day_slots[i+j])
                            break
            i += colspan
        
        template_routine_data['days'].append({
            'day': day_obj.name,
            'status': day_obj.status.slug if day_obj.status else 'available-day',
            'slots': final_day_slots,
        })

    # ReportLab Generation
    buffer = BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=landscape(A4), rightMargin=1*cm, leftMargin=1*cm, topMargin=1*cm, bottomMargin=1*cm)
    elements = []
    styles = getSampleStyleSheet()
    
    # Custom Styles
    title_style = ParagraphStyle('TitleStyle', parent=styles['Heading1'], alignment=TA_CENTER, fontSize=16, spaceAfter=2)
    subtitle_style = ParagraphStyle('SubtitleStyle', parent=styles['Heading3'], alignment=TA_CENTER, fontSize=12, spaceAfter=2)
    info_style = ParagraphStyle('InfoStyle', parent=styles['Normal'], alignment=TA_CENTER, fontSize=10, spaceAfter=10)
    table_cell_style = ParagraphStyle('TableCellStyle', fontSize=8, alignment=TA_CENTER, leading=9)

    # Header
    elements.append(Paragraph("Ahsania Mission University of Science & Technology", title_style))
    elements.append(Paragraph(template_routine_data['department']['department_name'], subtitle_style))
    elements.append(Paragraph(f"Class Routine {template_routine_data['semester']['title']}-{template_routine_data['routine_year']} ({template_routine_data['batch']['batch_name']}, {template_routine_data['year']['title']}, {template_routine_data['semester']['title']} Semester)", info_style))
    elements.append(Paragraph(f"(Effective from {template_routine_data['effective_from']})", info_style))
    elements.append(Spacer(1, 0.5*cm))

    # Routine Table Data
    table_data = []
    
    # Header Row 1: Day/Time + Slot Names
    header1 = [Paragraph("Day / Time", table_cell_style)]
    for ts in timeslots:
        header1.append(Paragraph(ts['slot_name'], table_cell_style))
    table_data.append(header1)

    # Header Row 2: Empty + Start-End Times
    header2 = [""]
    for ts in timeslots:
        header2.append(Paragraph(f"{ts['start_time']}-{ts['end_time']}", table_cell_style))
    table_data.append(header2)

    # Day Rows
    for day_data in template_routine_data['days']:
        if day_data['status'] == 'weekend-day':
            continue
            
        row = [Paragraph(day_data['day'], table_cell_style)]
        for slot in day_data['slots']:
            if slot['type'] == 'hidden':
                row.append("")
                continue
            
            content = ""
            if slot['type'] == 'Available':
                content = f"{slot['course']['code']}<br/>{slot['teacher']['code']}"
                if slot['room']:
                    content += f"<br/>Room: {slot['room']['room_number']}"
            elif slot['type'] == 'break':
                content = slot['content']
            
            row.append(Paragraph(content, table_cell_style))
        table_data.append(row)

    # Table Styling
    num_cols = len(timeslots) + 1
    routine_table = Table(table_data, colWidths=[1.5*cm] + [(doc.width - 1.5*cm)/len(timeslots)] * len(timeslots))
    
    routine_table_style = [
        ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ('BACKGROUND', (0, 0), (-1, 1), colors.whitesmoke),
        ('SPAN', (0, 0), (0, 1)), # Span Day/Time header
    ]

    # Apply Colspans and Backgrounds
    row_idx = 2
    for day_data in template_routine_data['days']:
        if day_data['status'] == 'weekend-day':
            continue
        
        col_idx = 1
        for slot in day_data['slots']:
            if slot['type'] == 'hidden':
                continue
            
            if slot['colspan'] > 1:
                routine_table_style.append(('SPAN', (col_idx, row_idx), (col_idx + slot['colspan'] - 1, row_idx)))
            
            if slot['type'] == 'break':
                routine_table_style.append(('BACKGROUND', (col_idx, row_idx), (col_idx + slot['colspan'] - 1, row_idx), colors.lightyellow))
            
            col_idx += slot['colspan']
        row_idx += 1

    routine_table.setStyle(TableStyle(routine_table_style))
    elements.append(routine_table)
    elements.append(Spacer(1, 1*cm))

    # Faculty and Course List (Footer Tables)
    footer_data = []
    
    # Left side: Faculty Members
    faculty_list = []
    if not template_routine_data['all_teachers']:
        faculty_list.append("No faculty members found.")
    else:
        for t in template_routine_data['all_teachers']:
            faculty_list.append(f"{t['code']} - {t['first_name']} {t['last_name']}")
    
    faculty_para = [Paragraph("<b>Faculty Members</b>", subtitle_style)] + [Paragraph(f"• {f}", table_cell_style) for f in faculty_list]
    
    # Right side: Course List
    course_list = []
    if not template_routine_data['all_courses']:
        course_list.append("No courses found.")
    else:
        for c in template_routine_data['all_courses']:
            teachers_str = ""
            if c.get('teachers'):
                teachers_list = [f"{t['first_name']} {t['last_name']}" for t in c['teachers']]
                teachers_str = f" ({', '.join(teachers_list)})"
            course_list.append(f"{c['code']} - {c['name']}{teachers_str}")
            
    course_para = [Paragraph("<b>Course List</b>", subtitle_style)] + [Paragraph(f"• {c}", table_cell_style) for c in course_list]
    
    footer_table = Table([[faculty_para, course_para]], colWidths=[doc.width/2.0]*2)
    footer_table.setStyle(TableStyle([
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('LEFTPADDING', (0, 0), (-1, -1), 10),
        ('RIGHTPADDING', (0, 0), (-1, -1), 10),
    ]))
    elements.append(footer_table)

    doc.build(elements)
    
    pdf = buffer.getvalue()
    buffer.close()
    
    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="routine_{routine_slug}.pdf"'
    return response