"""
Klausur-Service Grading Routes

Endpoints for grading, Gutachten, and examiner workflow.
"""

from datetime import datetime, timezone

from fastapi import APIRouter, HTTPException, Request

from models.enums import StudentKlausurStatus
from models.grading import GRADE_LABELS, DEFAULT_CRITERIA
from models.requests import (
    CriterionScoreUpdate,
    GutachtenUpdate,
    GutachtenGenerateRequest,
    ExaminerAssignment,
    ExaminerResult,
)
from services.auth_service import get_current_user
from services.grading_service import calculate_grade_points, calculate_raw_points
from services.eh_service import log_audit, log_eh_audit
from config import OPENAI_API_KEY
import storage

# BYOEH imports (conditional)
try:
    from korrektur.eh_pipeline import decrypt_text, EncryptionError
    from qdrant_service import search_eh
    from korrektur.eh_pipeline import generate_single_embedding
    BYOEH_AVAILABLE = True
except ImportError:
    BYOEH_AVAILABLE = False

router = APIRouter()


@router.put("/api/v1/students/{student_id}/criteria")
async def update_criteria(student_id: str, data: CriterionScoreUpdate, request: Request):
    """Update a criterion score for a student."""
    user = get_current_user(request)

    if student_id not in storage.students_db:
        raise HTTPException(status_code=404, detail="Student work not found")

    student = storage.students_db[student_id]

    # Get old value for audit
    old_score = student.criteria_scores.get(data.criterion, {}).get("score", 0)

    student.criteria_scores[data.criterion] = {
        "score": data.score,
        "annotations": data.annotations or []
    }

    # Recalculate points
    student.raw_points = calculate_raw_points(student.criteria_scores)
    student.grade_points = calculate_grade_points(student.raw_points)

    # Audit log
    log_audit(
        user_id=user["user_id"],
        action="score_update",
        entity_type="student",
        entity_id=student_id,
        field=data.criterion,
        old_value=str(old_score),
        new_value=str(data.score)
    )

    return student.to_dict()


@router.put("/api/v1/students/{student_id}/gutachten")
async def update_gutachten(student_id: str, data: GutachtenUpdate, request: Request):
    """Update the Gutachten for a student."""
    user = get_current_user(request)

    if student_id not in storage.students_db:
        raise HTTPException(status_code=404, detail="Student work not found")

    student = storage.students_db[student_id]
    had_gutachten = student.gutachten is not None

    student.gutachten = {
        "einleitung": data.einleitung,
        "hauptteil": data.hauptteil,
        "fazit": data.fazit,
        "staerken": data.staerken or [],
        "schwaechen": data.schwaechen or [],
        "updated_at": datetime.now(timezone.utc).isoformat()
    }

    # Audit log
    log_audit(
        user_id=user["user_id"],
        action="gutachten_update",
        entity_type="student",
        entity_id=student_id,
        field="gutachten",
        old_value="existing" if had_gutachten else "none",
        new_value="updated",
        details={"sections": ["einleitung", "hauptteil", "fazit"]}
    )

    return student.to_dict()


@router.post("/api/v1/students/{student_id}/finalize")
async def finalize_student(student_id: str, request: Request):
    """Finalize a student's grade."""
    user = get_current_user(request)

    if student_id not in storage.students_db:
        raise HTTPException(status_code=404, detail="Student work not found")

    student = storage.students_db[student_id]
    old_status = student.status.value if hasattr(student.status, 'value') else student.status
    student.status = StudentKlausurStatus.COMPLETED

    # Audit log
    log_audit(
        user_id=user["user_id"],
        action="status_change",
        entity_type="student",
        entity_id=student_id,
        field="status",
        old_value=old_status,
        new_value="completed"
    )

    return student.to_dict()


@router.post("/api/v1/students/{student_id}/gutachten/generate")
async def generate_gutachten(student_id: str, data: GutachtenGenerateRequest, request: Request):
    """
    Generate a KI-based Gutachten for a student's work.

    Optionally uses RAG context from the teacher's Erwartungshorizonte
    if use_eh=True and eh_passphrase is provided.
    """
    user = get_current_user(request)

    if student_id not in storage.students_db:
        raise HTTPException(status_code=404, detail="Student work not found")

    student = storage.students_db[student_id]
    klausur = storage.klausuren_db.get(student.klausur_id)

    if not klausur:
        raise HTTPException(status_code=404, detail="Klausur not found")

    # BYOEH RAG Context (optional)
    eh_context = ""
    eh_sources = []
    if BYOEH_AVAILABLE and data.use_eh and data.eh_passphrase and OPENAI_API_KEY:
        tenant_id = user.get("tenant_id") or user.get("school_id") or user["user_id"]
        try:
            # Use first part of student's OCR text as query
            query_text = ""
            if student.ocr_text:
                query_text = student.ocr_text[:1000]
            else:
                query_text = f"Klausur {klausur.subject} {klausur.title}"

            # Generate query embedding
            query_embedding = await generate_single_embedding(query_text)

            # Search in Qdrant (tenant-isolated)
            results = await search_eh(
                query_embedding=query_embedding,
                tenant_id=tenant_id,
                subject=klausur.subject,
                limit=3
            )

            # Decrypt matching chunks
            for r in results:
                eh = storage.eh_db.get(r["eh_id"])
                if eh and r.get("encrypted_content"):
                    try:
                        decrypted = decrypt_text(
                            r["encrypted_content"],
                            data.eh_passphrase,
                            eh.salt
                        )
                        eh_sources.append({
                            "text": decrypted,
                            "eh_title": eh.title,
                            "score": r["score"]
                        })
                    except EncryptionError:
                        pass  # Skip chunks that can't be decrypted

            if eh_sources:
                eh_context = "\n\n--- Erwartungshorizont-Kontext ---\n"
                eh_context += "\n\n".join([s["text"] for s in eh_sources])

                # Audit log for RAG usage
                log_eh_audit(
                    tenant_id=tenant_id,
                    user_id=user["user_id"],
                    action="rag_query_gutachten",
                    details={
                        "student_id": student_id,
                        "sources_count": len(eh_sources)
                    }
                )

        except Exception as e:
            print(f"BYOEH RAG failed: {e}")
            # Continue without RAG context

    # Calculate overall percentage
    total_percentage = calculate_raw_points(student.criteria_scores)
    grade = calculate_grade_points(total_percentage)
    grade_label = GRADE_LABELS.get(grade, "")

    # Analyze criteria for strengths/weaknesses
    staerken = []
    schwaechen = []

    for criterion, score_data in student.criteria_scores.items():
        score = score_data.get("score", 0)
        label = DEFAULT_CRITERIA.get(criterion, {}).get("label", criterion)

        if score >= 80:
            staerken.append(f"Sehr gute Leistung im Bereich {label} ({score}%)")
        elif score >= 60:
            staerken.append(f"Solide Leistung im Bereich {label} ({score}%)")
        elif score < 40:
            schwaechen.append(f"Verbesserungsbedarf im Bereich {label} ({score}%)")
        elif score < 60:
            schwaechen.append(f"Ausbaufaehiger Bereich: {label} ({score}%)")

    # Generate Gutachten text based on scores
    if total_percentage >= 85:
        einleitung = f"Die vorliegende Arbeit von {student.student_name} zeigt eine hervorragende Leistung."
        hauptteil = f"""Die Arbeit ueberzeugt durch eine durchweg starke Bearbeitung der gestellten Aufgaben.
Die inhaltliche Auseinandersetzung mit dem Thema ist tiefgruendig und zeigt ein fundiertes Verstaendnis.
Die sprachliche Gestaltung ist praezise und dem Anlass angemessen.
Die Argumentation ist schluessig und wird durch treffende Beispiele gestuetzt."""
        fazit = f"Insgesamt eine sehr gelungene Arbeit, die mit {grade} Punkten ({grade_label}) bewertet wird."

    elif total_percentage >= 65:
        einleitung = f"Die Arbeit von {student.student_name} zeigt eine insgesamt gute Leistung mit einzelnen Staerken."
        hauptteil = f"""Die Bearbeitung der Aufgaben erfolgt weitgehend vollstaendig und korrekt.
Die inhaltliche Analyse zeigt ein solides Verstaendnis des Themas.
Die sprachliche Gestaltung ist ueberwiegend angemessen, mit kleineren Unsicherheiten.
Die Struktur der Arbeit ist nachvollziehbar."""
        fazit = f"Die Arbeit wird mit {grade} Punkten ({grade_label}) bewertet. Es bestehen Moeglichkeiten zur weiteren Verbesserung."

    elif total_percentage >= 45:
        einleitung = f"Die Arbeit von {student.student_name} erfuellt die grundlegenden Anforderungen."
        hauptteil = f"""Die Aufgabenstellung wird im Wesentlichen bearbeitet, jedoch bleiben einige Aspekte unterbeleuchtet.
Die inhaltliche Auseinandersetzung zeigt grundlegende Kenntnisse, bedarf aber weiterer Vertiefung.
Die sprachliche Gestaltung weist Unsicherheiten auf, die die Klarheit beeintraechtigen.
Die Struktur koennte stringenter sein."""
        fazit = f"Die Arbeit wird mit {grade} Punkten ({grade_label}) bewertet. Empfohlen wird eine intensivere Auseinandersetzung mit der Methodik."

    else:
        einleitung = f"Die Arbeit von {student.student_name} weist erhebliche Defizite auf."
        hauptteil = f"""Die Bearbeitung der Aufgaben bleibt unvollstaendig oder geht nicht ausreichend auf die Fragestellung ein.
Die inhaltliche Analyse zeigt Luecken im Verstaendnis des Themas.
Die sprachliche Gestaltung erschwert das Verstaendnis erheblich.
Die Arbeit laesst eine klare Struktur vermissen."""
        fazit = f"Die Arbeit wird mit {grade} Punkten ({grade_label}) bewertet. Dringend empfohlen wird eine grundlegende Wiederholung der Thematik."

    generated_gutachten = {
        "einleitung": einleitung,
        "hauptteil": hauptteil,
        "fazit": fazit,
        "staerken": staerken if data.include_strengths else [],
        "schwaechen": schwaechen if data.include_weaknesses else [],
        "generated_at": datetime.now(timezone.utc).isoformat(),
        "is_ki_generated": True,
        "tone": data.tone,
        # BYOEH RAG Integration
        "eh_context_used": len(eh_sources) > 0,
        "eh_sources": [
            {"title": s["eh_title"], "score": s["score"]}
            for s in eh_sources
        ] if eh_sources else []
    }

    # Audit log
    log_audit(
        user_id=user["user_id"],
        action="gutachten_generate",
        entity_type="student",
        entity_id=student_id,
        details={
            "tone": data.tone,
            "grade": grade,
            "eh_context_used": len(eh_sources) > 0,
            "eh_sources_count": len(eh_sources)
        }
    )

    return generated_gutachten


# =============================================
# EXAMINER WORKFLOW
# =============================================

@router.post("/api/v1/students/{student_id}/examiner")
async def assign_examiner(student_id: str, data: ExaminerAssignment, request: Request):
    """Assign an examiner (first or second) to a student's work."""
    user = get_current_user(request)

    if student_id not in storage.students_db:
        raise HTTPException(status_code=404, detail="Student work not found")

    student = storage.students_db[student_id]

    # Initialize examiner record if not exists
    if student_id not in storage.examiner_db:
        storage.examiner_db[student_id] = {
            "first_examiner": None,
            "second_examiner": None,
            "first_result": None,
            "second_result": None,
            "consensus_reached": False,
            "final_grade": None
        }

    exam_record = storage.examiner_db[student_id]

    if data.examiner_role == "first_examiner":
        exam_record["first_examiner"] = {
            "id": data.examiner_id,
            "assigned_at": datetime.now(timezone.utc).isoformat(),
            "notes": data.notes
        }
        student.status = StudentKlausurStatus.FIRST_EXAMINER
    elif data.examiner_role == "second_examiner":
        exam_record["second_examiner"] = {
            "id": data.examiner_id,
            "assigned_at": datetime.now(timezone.utc).isoformat(),
            "notes": data.notes
        }
        student.status = StudentKlausurStatus.SECOND_EXAMINER
    else:
        raise HTTPException(status_code=400, detail="Invalid examiner role")

    # Audit log
    log_audit(
        user_id=user["user_id"],
        action="examiner_assign",
        entity_type="student",
        entity_id=student_id,
        field=data.examiner_role,
        new_value=data.examiner_id
    )

    return {
        "success": True,
        "student_id": student_id,
        "examiner": exam_record
    }


@router.post("/api/v1/students/{student_id}/examiner/result")
async def submit_examiner_result(student_id: str, data: ExaminerResult, request: Request):
    """Submit an examiner's grading result."""
    user = get_current_user(request)

    if student_id not in storage.students_db:
        raise HTTPException(status_code=404, detail="Student work not found")

    if student_id not in storage.examiner_db:
        raise HTTPException(status_code=400, detail="No examiner assigned")

    exam_record = storage.examiner_db[student_id]
    user_id = user["user_id"]

    # Determine which examiner is submitting
    if exam_record.get("first_examiner", {}).get("id") == user_id:
        exam_record["first_result"] = {
            "grade_points": data.grade_points,
            "notes": data.notes,
            "submitted_at": datetime.now(timezone.utc).isoformat()
        }
    elif exam_record.get("second_examiner", {}).get("id") == user_id:
        exam_record["second_result"] = {
            "grade_points": data.grade_points,
            "notes": data.notes,
            "submitted_at": datetime.now(timezone.utc).isoformat()
        }
    else:
        raise HTTPException(status_code=403, detail="You are not assigned as examiner")

    # Check if both results are in and calculate consensus
    if exam_record["first_result"] and exam_record["second_result"]:
        first_grade = exam_record["first_result"]["grade_points"]
        second_grade = exam_record["second_result"]["grade_points"]
        diff = abs(first_grade - second_grade)

        if diff <= 2:
            # Automatic consensus: average
            exam_record["final_grade"] = round((first_grade + second_grade) / 2)
            exam_record["consensus_reached"] = True
            storage.students_db[student_id].grade_points = exam_record["final_grade"]
            storage.students_db[student_id].status = StudentKlausurStatus.COMPLETED
        else:
            # Needs discussion
            exam_record["consensus_reached"] = False
            exam_record["needs_discussion"] = True

    # Audit log
    log_audit(
        user_id=user_id,
        action="examiner_result",
        entity_type="student",
        entity_id=student_id,
        new_value=str(data.grade_points)
    )

    return exam_record


@router.get("/api/v1/students/{student_id}/examiner")
async def get_examiner_status(student_id: str, request: Request):
    """Get the examiner assignment and results for a student."""
    user = get_current_user(request)

    if student_id not in storage.students_db:
        raise HTTPException(status_code=404, detail="Student work not found")

    return storage.examiner_db.get(student_id, {
        "first_examiner": None,
        "second_examiner": None,
        "first_result": None,
        "second_result": None,
        "consensus_reached": False,
        "final_grade": None
    })
