from django.contrib.auth.decorators import login_required
import json
import os
from datetime import timedelta
import logging
import requests

from django.http import HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.utils import timezone
from django.core.exceptions import ValidationError

from schools.access import get_user_school, user_has_permission
from schools.models import ClassRoom, TermDate, TeacherAssignment, StreamClassTeacher, Subject as SchoolSubject

from .models import Subject, SyllabusDocument, SyllabusTopic, SyllabusSubtopic, SchemePlan
from .utils.syllabus_parser import extract_text_from_file, parse_topics_and_subtopics


logger = logging.getLogger(__name__)

def _teacher_scope_or_forbidden(request):
    school = get_user_school(request.user)
    if not school:
        return None
    if getattr(request.user, 'teacher', None) or user_has_permission(request.user, school, 'academics_teacher'):
        return school
    return None


def _academics_scope_or_forbidden(request):
    school = get_user_school(request.user)
    if not school:
        return None
    if user_has_permission(request.user, school, 'academics') or user_has_permission(request.user, school, 'academics_teacher'):
        return school
    return None

@login_required
def teacher_dashboard(request):
    return render(request, 'academics/teacher_dashboard.html')


@login_required
def scheme_generator(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return HttpResponseForbidden('Only teachers can access this module.')
    classes = ClassRoom.objects.filter(school=school).order_by('order', 'name')
    subjects = SchoolSubject.objects.filter(school=school).order_by('name')
    if hasattr(request.user, 'teacher'):
        teacher = request.user.teacher
        assigned_class_ids = set(
            TeacherAssignment.objects.filter(
                teacher=teacher,
                classroom__school=school,
            ).values_list('classroom_id', flat=True)
        )
        assigned_class_ids.update(
            StreamClassTeacher.objects.filter(
                teacher=teacher,
                classroom__school=school,
            ).values_list('classroom_id', flat=True)
        )
        assigned_class_ids.update(
            ClassRoom.objects.filter(
                school=school,
                class_teacher=teacher,
            ).values_list('id', flat=True)
        )
        assigned_subject_ids = set(
            TeacherAssignment.objects.filter(
                teacher=teacher,
                classroom__school=school,
            ).values_list('subject_id', flat=True)
        )
        classes = classes.filter(id__in=assigned_class_ids) if assigned_class_ids else ClassRoom.objects.none()
        subjects = subjects.filter(id__in=assigned_subject_ids) if assigned_subject_ids else SchoolSubject.objects.none()
    term_dates = TermDate.objects.filter(school=school).order_by('-year', '-term').first()
    terms = [
        {'id': td.id, 'label': f"{td.term} {td.year}"} for td in TermDate.objects.filter(school=school).order_by('-year', '-term')
    ]
    context = {
        'school_name': school.name,
        'school_logo_url': getattr(school, 'logo', None).url if getattr(school, 'logo', None) else '',
        'curriculum_type': getattr(school, 'school_type', '') or '',
        'classes': classes,
        'subjects': subjects,
        'terms': terms or [{'id': 'term1', 'label': 'Term 1'}, {'id': 'term2', 'label': 'Term 2'}, {'id': 'term3', 'label': 'Term 3'}],
        'term_dates': {
            'opening_date': term_dates.start_date if term_dates else '',
            'midterm_date': '',
            'closing_date': term_dates.end_date if term_dates else '',
            'total_weeks': ((term_dates.end_date - term_dates.start_date).days // 7 + 1) if term_dates else '',
        } if term_dates else None,
    }
    return render(request, 'academics/scheme_generator.html', context)


def _latest_syllabus_document(school, subject_id, class_id):
    classroom = None
    if class_id:
        classroom = ClassRoom.objects.filter(id=class_id, school=school).select_related('level').first()
    curriculum = getattr(school, "school_type", "") or ""
    base_qs = SyllabusDocument.objects.filter(subject_id=subject_id, curriculum_type=curriculum)
    if classroom:
        base_qs = base_qs.filter(classroom_id=classroom.id)
    doc = base_qs.order_by('-uploaded_at').first()
    if doc:
        return doc
    if classroom and classroom.level_id:
        return SyllabusDocument.objects.filter(
            subject_id=subject_id,
            education_level_id=classroom.level_id,
            curriculum_type=curriculum,
        ).order_by('-uploaded_at').first()
    return SyllabusDocument.objects.filter(
        subject_id=subject_id,
        curriculum_type=curriculum,
    ).order_by('-uploaded_at').first()


def _ensure_syllabus_topics(document: SyllabusDocument):
    if not document:
        return
    if document.topics.exists():
        return
    try:
        with document.document.open('rb') as f:
            text = extract_text_from_file(f, getattr(document.document, 'name', ''))
    except Exception:
        text = ''
    if not text:
        return
    parsed = parse_topics_and_subtopics(text)
    order = 1
    for entry in parsed:
        title = str(entry.get('title') or '').strip()
        if not title:
            continue
        topic = SyllabusTopic.objects.create(document=document, title=title, order=order)
        sub_order = 1
        for sub in entry.get('subtopics') or []:
            sub_title = str(sub).strip()
            if not sub_title:
                continue
            SyllabusSubtopic.objects.create(topic=topic, title=sub_title, order=sub_order)
            sub_order += 1
        order += 1


@login_required
def scheme_topics(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return JsonResponse({'topics': []})
    subject_id = request.GET.get('subject_id')
    class_id = request.GET.get('class_id')
    if not subject_id:
        return JsonResponse({'topics': []})
    document = _latest_syllabus_document(school, subject_id, class_id)
    if not document:
        return JsonResponse({'topics': []})
    _ensure_syllabus_topics(document)
    topics = [
        {'id': t.id, 'title': t.title}
        for t in document.topics.all().order_by('order', 'id')
    ]
    return JsonResponse({'topics': topics})


@login_required
def scheme_subtopics(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return JsonResponse({'subtopics': []})
    topic_id = request.GET.get('topic_id')
    if not topic_id:
        return JsonResponse({'subtopics': []})
    topic = SyllabusTopic.objects.filter(id=topic_id).select_related('document').first()
    if not topic:
        return JsonResponse({'subtopics': []})
    subtopics = [
        {'id': s.id, 'title': s.title}
        for s in topic.subtopics.all().order_by('order', 'id')
    ]
    return JsonResponse({'subtopics': subtopics})


def _build_scheme_rows(subtopics, total_weeks, opening_date):
    rows = []
    week_date = opening_date
    for idx in range(total_weeks):
        if idx < len(subtopics):
            item = subtopics[idx]
            topic = item['topic']
            sub = item['subtopic']
            activities = f"Introduce {sub} with class discussion."
            resources = "Textbook, worksheet, board work."
            assessment = f"Short quiz on {sub}."
        else:
            topic = "Revision / Assessment"
            sub = "Review and practice"
            activities = "Revision exercises and group work."
            resources = "Revision worksheets."
            assessment = "Weekly assessment."
        date_label = week_date.strftime('%Y-%m-%d') if week_date else '—'
        rows.append({
            'week': f"Week {idx + 1}",
            'date': date_label,
            'topic': topic,
            'subtopic': sub,
            'activities': activities,
            'resources': resources,
            'assessment': assessment,
        })
        if week_date:
            week_date = week_date + timedelta(days=7)
    return rows


def _openai_request(payload: dict):
    api_key = (os.environ.get("OPENAI_API_KEY") or "").strip()
    if not api_key:
        return None, "OPENAI_API_KEY is not configured."
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    }
    try:
        resp = requests.post(
            "https://api.openai.com/v1/responses",
            headers=headers,
            json=payload,
            timeout=90,
        )
    except requests.RequestException as exc:
        logger.exception("OpenAI request failed")
        return None, f"OpenAI request failed: {exc}"
    if resp.status_code >= 400:
        try:
            detail = resp.json().get("error", {}).get("message", "")
        except ValueError:
            detail = resp.text or ""
        msg = f"OpenAI API error ({resp.status_code})."
        if detail:
            msg = f"{msg} {detail}"
        return None, msg
    try:
        return resp.json(), None
    except ValueError:
        return None, "OpenAI API returned invalid JSON."


def _extract_openai_json(output: dict):
    if not output:
        return None, "Empty OpenAI response."
    if output.get("error"):
        return None, output["error"].get("message", "OpenAI error.")
    if output.get("refusal"):
        return None, "OpenAI refused to generate the response."
    if output.get("output_text"):
        try:
            return json.loads(output["output_text"]), None
        except ValueError:
            return None, "OpenAI returned non-JSON output."
    for item in output.get("output", []):
        for content in item.get("content", []):
            if content.get("type") == "refusal":
                return None, "OpenAI refused to generate the response."
            if content.get("type") in ("output_text", "text") and content.get("text"):
                try:
                    return json.loads(content["text"]), None
                except ValueError:
                    return None, "OpenAI returned non-JSON output."
    return None, "OpenAI response did not include JSON content."


def _week_date_label(opening_date, week_index: int) -> str:
    if not opening_date:
        return "—"
    try:
        return (opening_date + timedelta(days=7 * (week_index - 1))).strftime("%Y-%m-%d")
    except Exception:
        return "—"


@login_required
def generate_scheme(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return JsonResponse({'success': False, 'error': 'Not allowed'}, status=403)
    try:
        payload = json.loads(request.body or '{}')
    except json.JSONDecodeError:
        payload = {}

    class_id = payload.get('class_id')
    subject_id = payload.get('subject_id')
    term_id = payload.get('term_id')
    start_topic_id = payload.get('topic_id')
    start_subtopic_id = payload.get('subtopic_id')
    manual_weeks = int(payload.get('manual_weeks') or 0)

    if not class_id or not subject_id:
        return JsonResponse({'success': False, 'error': 'Missing class or subject.'}, status=400)
    if not Subject.objects.filter(id=subject_id, school=school).exists():
        return JsonResponse({'success': False, 'error': 'Invalid subject selection.'}, status=400)

    document = _latest_syllabus_document(school, subject_id, class_id)
    if not document:
        return JsonResponse({'success': False, 'error': 'No syllabus document found for this class and subject.'}, status=404)
    _ensure_syllabus_topics(document)

    topics = list(document.topics.all().order_by('order', 'id'))
    if not topics:
        return JsonResponse({'success': False, 'error': 'Syllabus topics could not be extracted.'}, status=400)

    start_topic = None
    if start_topic_id:
        start_topic = next((t for t in topics if str(t.id) == str(start_topic_id)), None)
    if not start_topic:
        start_topic = topics[0]

    subtopics_qs = SyllabusSubtopic.objects.filter(topic__document=document).select_related('topic').order_by('topic__order', 'order', 'id')
    subtopics = [{'id': s.id, 'topic': s.topic.title, 'subtopic': s.title} for s in subtopics_qs]
    if start_subtopic_id:
        for idx, item in enumerate(subtopics):
            if str(item['id']) == str(start_subtopic_id):
                subtopics = subtopics[idx:]
                break

    term_dates = TermDate.objects.filter(id=term_id).first() if term_id else None
    opening_date = term_dates.start_date if term_dates else None
    closing_date = term_dates.end_date if term_dates else None
    total_weeks = manual_weeks
    if term_dates and opening_date and closing_date:
        total_weeks = ((closing_date - opening_date).days // 7) + 1
    if total_weeks <= 0:
        total_weeks = max(len(subtopics), 8)

    rows = _build_scheme_rows(subtopics, total_weeks, opening_date)
    return JsonResponse({'success': True, 'rows': rows})


@login_required
def generate_scheme_ai(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return JsonResponse({'success': False, 'error': 'Not allowed'}, status=403)
    try:
        payload = json.loads(request.body or '{}')
    except json.JSONDecodeError:
        payload = {}

    class_id = payload.get('class_id')
    subject_id = payload.get('subject_id')
    term_id = payload.get('term_id')
    topics = payload.get('topics') or []
    lessons_per_week = int(payload.get('lessons_per_week') or 0)
    manual_weeks = int(payload.get('manual_weeks') or 0)

    if not class_id or not subject_id:
        return JsonResponse({'success': False, 'error': 'Missing class or subject.'}, status=400)
    if not isinstance(topics, list) or not [t for t in topics if str(t).strip()]:
        return JsonResponse({'success': False, 'error': 'Topics are required.'}, status=400)
    if lessons_per_week <= 0:
        return JsonResponse({'success': False, 'error': 'Lessons per week must be greater than zero.'}, status=400)

    classroom = ClassRoom.objects.filter(id=class_id, school=school).select_related('level').first()
    subject = SchoolSubject.objects.filter(id=subject_id, school=school).first()
    if not classroom or not subject:
        return JsonResponse({'success': False, 'error': 'Invalid class or subject selection.'}, status=400)

    if hasattr(request.user, 'teacher') and not (hasattr(request.user, 'headteacher') or request.user.is_superuser):
        has_assignment = TeacherAssignment.objects.filter(
            teacher=request.user.teacher,
            classroom_id=class_id,
            subject_id=subject_id,
            classroom__school=school,
        ).exists()
        if not has_assignment:
            return JsonResponse({'success': False, 'error': 'Not allowed for this class/subject.'}, status=403)

    term_dates = TermDate.objects.filter(id=term_id).first() if term_id else None
    opening_date = term_dates.start_date if term_dates else None
    closing_date = term_dates.end_date if term_dates else None
    total_weeks = manual_weeks
    if term_dates and opening_date and closing_date:
        total_weeks = ((closing_date - opening_date).days // 7) + 1
    if total_weeks <= 0:
        total_weeks = max(len(topics), 8)
    total_lessons = total_weeks * lessons_per_week

    topic_list = [str(t).strip() for t in topics if str(t).strip()]
    curriculum = getattr(school, "school_type", "") or "CBE"
    prompt = (
        "Create a scheme of work in JSON. "
        f"Curriculum: {curriculum}. Class/Year: {classroom.name}. Subject: {subject.name}. "
        f"Total weeks: {total_weeks}. Lessons per week: {lessons_per_week}. "
        f"Total lessons: {total_lessons}. Topics for the term (in order): {', '.join(topic_list)}. "
        "Generate subtopics for each topic and distribute them across lessons. "
        "If there are more lessons than subtopics, add review, practice, or assessment lessons. "
        "Use 'Week X - Lesson Y' for the week field. "
        "Return concise activities, resources, and assessments."
    )

    response_payload = {
        "model": os.environ.get("OPENAI_MODEL", "gpt-4o-mini"),
        "input": [
            {"role": "system", "content": "You are an expert curriculum planner."},
            {"role": "user", "content": prompt},
        ],
        "text": {
            "format": {
                "type": "json_schema",
                "name": "scheme_rows",
                "schema": {
                    "type": "object",
                    "additionalProperties": False,
                    "properties": {
                        "rows": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "additionalProperties": False,
                                "properties": {
                                    "week": {"type": "string"},
                                    "date": {"type": "string"},
                                    "topic": {"type": "string"},
                                    "subtopic": {"type": "string"},
                                    "activities": {"type": "string"},
                                    "resources": {"type": "string"},
                                    "assessment": {"type": "string"},
                                },
                                "required": ["week", "date", "topic", "subtopic", "activities", "resources", "assessment"],
                            },
                        }
                    },
                    "required": ["rows"],
                },
            }
        },
    }

    ai_resp, err = _openai_request(response_payload)
    if err:
        return JsonResponse({'success': False, 'error': err}, status=500)
    parsed, err = _extract_openai_json(ai_resp)
    if err:
        return JsonResponse({'success': False, 'error': err}, status=500)

    rows = parsed.get("rows") if isinstance(parsed, dict) else None
    if not rows:
        return JsonResponse({'success': False, 'error': 'No scheme rows generated.'}, status=500)

    # Fill dates if missing and term dates exist.
    if opening_date:
        for idx, row in enumerate(rows, start=1):
            date_val = (row.get("date") or "").strip()
            if not date_val or date_val == "—":
                row["date"] = _week_date_label(opening_date, ((idx - 1) // lessons_per_week) + 1)

    term_label = ''
    if term_dates:
        term_label = f"{term_dates.term} {term_dates.year}"

    try:
        SchemePlan.objects.update_or_create(
            school=school,
            classroom=classroom,
            subject=subject,
            term_date=term_dates,
            defaults={
                'term_label': term_label,
                'curriculum_type': curriculum,
                'topics_text': "\n".join(topic_list),
                'lessons_per_week': lessons_per_week,
                'weeks_count': total_weeks,
                'rows': rows,
                'created_by': request.user,
            },
        )
    except Exception:
        logger.exception("Failed to save scheme plan")

    return JsonResponse({'success': True, 'rows': rows})


@login_required
def generate_lessonplan_ai(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return JsonResponse({'success': False, 'error': 'Not allowed'}, status=403)
    try:
        payload = json.loads(request.body or '{}')
    except json.JSONDecodeError:
        payload = {}

    class_id = payload.get('class_id')
    subject_id = payload.get('subject_id')
    topic = (payload.get('topic') or '').strip()
    subtopic = (payload.get('subtopic') or '').strip()
    lesson_date = (payload.get('lesson_date') or '').strip()
    lesson_length = int(payload.get('lesson_length_minutes') or 0)
    objectives = (payload.get('objectives') or '').strip()
    activities = (payload.get('activities') or '').strip()
    assessment = (payload.get('assessment') or '').strip()
    reflection = (payload.get('reflection') or '').strip()

    if not class_id or not subject_id or not topic:
        return JsonResponse({'success': False, 'error': 'Class, subject, and topic are required.'}, status=400)

    classroom = ClassRoom.objects.filter(id=class_id, school=school).first()
    subject = SchoolSubject.objects.filter(id=subject_id, school=school).first()
    if not classroom or not subject:
        return JsonResponse({'success': False, 'error': 'Invalid class or subject selection.'}, status=400)

    if hasattr(request.user, 'teacher') and not (hasattr(request.user, 'headteacher') or request.user.is_superuser):
        has_assignment = TeacherAssignment.objects.filter(
            teacher=request.user.teacher,
            classroom_id=class_id,
            subject_id=subject_id,
            classroom__school=school,
        ).exists()
        if not has_assignment:
            return JsonResponse({'success': False, 'error': 'Not allowed for this class/subject.'}, status=403)

    curriculum = getattr(school, "school_type", "") or "CBE"
    prompt = (
        "Create a detailed lesson plan in JSON. "
        f"Curriculum: {curriculum}. Class/Year: {classroom.name}. Subject: {subject.name}. "
        f"Topic: {topic}. Subtopic: {subtopic or 'N/A'}. "
        f"Lesson date: {lesson_date or 'N/A'}. Lesson length (mins): {lesson_length or 'N/A'}. "
        f"Teacher objectives: {objectives or 'N/A'}. "
        f"Teacher activities: {activities or 'N/A'}. "
        f"Assessment preference: {assessment or 'N/A'}. "
        f"Reflection notes: {reflection or 'N/A'}. "
        "Return a structured plan with objectives, materials, steps, assessment, and differentiation."
    )

    response_payload = {
        "model": os.environ.get("OPENAI_MODEL", "gpt-4o-mini"),
        "input": [
            {"role": "system", "content": "You are an expert lesson planner."},
            {"role": "user", "content": prompt},
        ],
        "text": {
            "format": {
                "type": "json_schema",
                "name": "lesson_plan",
                "schema": {
                    "type": "object",
                    "additionalProperties": False,
                    "properties": {
                        "title": {"type": "string"},
                        "objectives": {"type": "array", "items": {"type": "string"}},
                        "materials": {"type": "array", "items": {"type": "string"}},
                        "lesson_steps": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "additionalProperties": False,
                                "properties": {
                                    "phase": {"type": "string"},
                                    "duration_minutes": {"type": "number"},
                                    "activities": {"type": "string"},
                                },
                                "required": ["phase", "duration_minutes", "activities"],
                            },
                        },
                        "assessment": {"type": "string"},
                        "differentiation": {"type": "string"},
                        "homework": {"type": "string"},
                    },
                    "required": ["title", "objectives", "materials", "lesson_steps", "assessment"],
                },
            }
        },
    }

    ai_resp, err = _openai_request(response_payload)
    if err:
        return JsonResponse({'success': False, 'error': err}, status=500)
    parsed, err = _extract_openai_json(ai_resp)
    if err:
        return JsonResponse({'success': False, 'error': err}, status=500)

    return JsonResponse({'success': True, 'plan': parsed})


@login_required
def scheme_preview(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return JsonResponse({'success': False, 'error': 'Not allowed'}, status=403)
    class_id = request.GET.get('class_id')
    subject_id = request.GET.get('subject_id')
    term_id = request.GET.get('term_id')
    if not class_id or not subject_id or not term_id:
        return JsonResponse({'success': False, 'error': 'Missing filters.'}, status=400)

    if hasattr(request.user, 'teacher') and not (hasattr(request.user, 'headteacher') or request.user.is_superuser):
        has_assignment = TeacherAssignment.objects.filter(
            teacher=request.user.teacher,
            classroom_id=class_id,
            subject_id=subject_id,
            classroom__school=school,
        ).exists()
        if not has_assignment:
            return JsonResponse({'success': False, 'error': 'Not allowed for this class/subject.'}, status=403)

    plan = SchemePlan.objects.filter(
        school=school,
        classroom_id=class_id,
        subject_id=subject_id,
        term_date_id=term_id,
    ).order_by('-updated_at').first()
    if not plan:
        return JsonResponse({'success': True, 'rows': []})
    return JsonResponse({'success': True, 'rows': plan.rows})


@login_required
def lessonplan_generator(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return HttpResponseForbidden('Only teachers can access this module.')
    classes = ClassRoom.objects.filter(school=school).order_by('order', 'name')
    subjects = SchoolSubject.objects.filter(school=school).order_by('name')
    if hasattr(request.user, 'teacher'):
        teacher = request.user.teacher
        assigned_class_ids = set(
            TeacherAssignment.objects.filter(
                teacher=teacher,
                classroom__school=school,
            ).values_list('classroom_id', flat=True)
        )
        assigned_class_ids.update(
            StreamClassTeacher.objects.filter(
                teacher=teacher,
                classroom__school=school,
            ).values_list('classroom_id', flat=True)
        )
        assigned_class_ids.update(
            ClassRoom.objects.filter(
                school=school,
                class_teacher=teacher,
            ).values_list('id', flat=True)
        )
        assigned_subject_ids = set(
            TeacherAssignment.objects.filter(
                teacher=teacher,
                classroom__school=school,
            ).values_list('subject_id', flat=True)
        )
        classes = classes.filter(id__in=assigned_class_ids) if assigned_class_ids else ClassRoom.objects.none()
        subjects = subjects.filter(id__in=assigned_subject_ids) if assigned_subject_ids else SchoolSubject.objects.none()
    context = {
        'school_name': school.name,
        'school_logo_url': getattr(school, 'logo', None).url if getattr(school, 'logo', None) else '',
        'curriculum_type': getattr(school, 'school_type', '') or '',
        'classes': classes,
        'subjects': subjects,
    }
    return render(request, 'academics/lessonplan_generator.html', context)


@login_required
def syllabus_coverage(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return HttpResponseForbidden('Only teachers can access this module.')
    context = {
        'school_name': school.name,
        'school_logo_url': getattr(school, 'logo', None).url if getattr(school, 'logo', None) else '',
        'curriculum_type': getattr(school, 'school_type', '') or '',
        'coverage_summary': {'subjects': 0, 'completed': 0, 'total': 0, 'percent': 0},
        'coverage_by_subject': [],
        'coverage_rows': [],
        'heatmap': [],
        'chart_data': {},
    }
    return render(request, 'academics/syllabus_coverage.html', context)


@login_required
def syllabus_upload(request):
    school = _academics_scope_or_forbidden(request)
    if not school:
        return HttpResponseForbidden('Not allowed.')

    classes = ClassRoom.objects.filter(school=school).order_by('order', 'name')
    subjects = Subject.objects.filter(school=school).order_by('name')
    errors = []
    success = False
    selected_subject_id = ''
    selected_class_id = ''
    selected_curriculum = ''

    if request.method == 'POST':
        selected_subject_id = (request.POST.get('subject_id') or '').strip()
        selected_class_id = (request.POST.get('class_id') or '').strip()
        selected_curriculum = (request.POST.get('curriculum_type') or SyllabusDocument.CURRICULUM_CBE).strip()

        document = request.FILES.get('document')
        sample_scheme = request.FILES.get('sample_scheme')
        sample_lesson_plan = request.FILES.get('sample_lesson_plan')

        subject = Subject.objects.filter(id=selected_subject_id, school=school).first() if selected_subject_id else None
        classroom = ClassRoom.objects.filter(id=selected_class_id, school=school).select_related('level').first() if selected_class_id else None

        if not subject:
            errors.append('Select a valid subject.')
        if not classroom:
            errors.append('Select a valid class.')
        if not document:
            errors.append('Upload a syllabus document.')

        if not errors:
            curriculum_keys = {key for key, _ in SyllabusDocument.CURRICULUM_CHOICES}
            curriculum = selected_curriculum if selected_curriculum in curriculum_keys else SyllabusDocument.CURRICULUM_CBE
            title = f"{subject.name} - {classroom.name}"
            record = SyllabusDocument(
                title=title,
                curriculum_type=curriculum,
                subject=subject,
                classroom=classroom,
                subject_name=subject.name,
                class_name=classroom.name,
                education_level=classroom.level if classroom else None,
                document=document,
                sample_scheme=sample_scheme,
                sample_lesson_plan=sample_lesson_plan,
            )
            try:
                record.full_clean()
                record.save()
                success = True
                selected_subject_id = ''
                selected_class_id = ''
                selected_curriculum = ''
            except ValidationError as exc:
                errors.extend(exc.messages)

    context = {
        'school_name': school.name,
        'school_logo_url': getattr(school, 'logo', None).url if getattr(school, 'logo', None) else '',
        'curriculum_type': getattr(school, 'school_type', '') or '',
        'classes': classes,
        'subjects': subjects,
        'errors': errors,
        'success': success,
        'selected_subject_id': selected_subject_id,
        'selected_class_id': selected_class_id,
        'selected_curriculum': selected_curriculum,
    }
    return render(request, 'admin/syllabus_upload.html', context)


@login_required
def resources_dashboard(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return HttpResponseForbidden('Only teachers can access this module.')
    return render(request, 'academics/resources.html', {
        'school_name': school.name,
        'school_logo_url': getattr(school, 'logo', None).url if getattr(school, 'logo', None) else '',
        'curriculum_type': getattr(school, 'school_type', '') or '',
    })


@login_required
def reports_dashboard(request):
    school = _teacher_scope_or_forbidden(request)
    if not school:
        return HttpResponseForbidden('Only teachers can access this module.')
    return render(request, 'academics/reports.html', {
        'school_name': school.name,
        'school_logo_url': getattr(school, 'logo', None).url if getattr(school, 'logo', None) else '',
        'curriculum_type': getattr(school, 'school_type', '') or '',
    })
