"""
Klausur-Service Fairness Routes

Endpoints for fairness analysis, audit logs, and utility functions.
"""

from typing import Optional

import httpx
from fastapi import APIRouter, HTTPException, Request

from models.grading import GRADE_THRESHOLDS, GRADE_LABELS, DEFAULT_CRITERIA
from services.auth_service import get_current_user
from config import SCHOOL_SERVICE_URL
import storage

router = APIRouter()


@router.get("/api/v1/klausuren/{klausur_id}/fairness")
async def get_fairness_analysis(klausur_id: str, request: Request):
    """Analyze grading fairness across all students in a Klausur."""
    user = get_current_user(request)

    if klausur_id not in storage.klausuren_db:
        raise HTTPException(status_code=404, detail="Klausur not found")

    klausur = storage.klausuren_db[klausur_id]
    students = klausur.students

    if len(students) < 2:
        return {
            "klausur_id": klausur_id,
            "analysis": "Zu wenige Arbeiten fuer Vergleich (mindestens 2 benoetigt)",
            "students_count": len(students)
        }

    # Calculate statistics
    grades = [s.grade_points for s in students if s.grade_points > 0]
    raw_points = [s.raw_points for s in students if s.raw_points > 0]

    if not grades:
        return {
            "klausur_id": klausur_id,
            "analysis": "Keine bewerteten Arbeiten vorhanden",
            "students_count": len(students)
        }

    avg_grade = sum(grades) / len(grades)
    avg_raw = sum(raw_points) / len(raw_points) if raw_points else 0
    min_grade = min(grades)
    max_grade = max(grades)
    spread = max_grade - min_grade

    # Calculate standard deviation
    variance = sum((g - avg_grade) ** 2 for g in grades) / len(grades)
    std_dev = variance ** 0.5

    # Identify outliers (more than 2 std deviations from mean)
    outliers = []
    for s in students:
        if s.grade_points > 0:
            deviation = abs(s.grade_points - avg_grade)
            if deviation > 2 * std_dev:
                outliers.append({
                    "student_id": s.id,
                    "student_name": s.student_name,
                    "grade_points": s.grade_points,
                    "deviation": round(deviation, 2),
                    "direction": "above" if s.grade_points > avg_grade else "below"
                })

    # Criteria comparison
    criteria_averages = {}
    for criterion in DEFAULT_CRITERIA.keys():
        scores = []
        for s in students:
            if criterion in s.criteria_scores:
                scores.append(s.criteria_scores[criterion].get("score", 0))
        if scores:
            criteria_averages[criterion] = {
                "average": round(sum(scores) / len(scores), 1),
                "min": min(scores),
                "max": max(scores),
                "count": len(scores)
            }

    # Fairness score (0-100, higher is more consistent)
    # Based on: low std deviation, no extreme outliers, reasonable spread
    fairness_score = 100
    if std_dev > 3:
        fairness_score -= min(30, std_dev * 5)
    if len(outliers) > 0:
        fairness_score -= len(outliers) * 10
    if spread > 10:
        fairness_score -= min(20, spread)
    fairness_score = max(0, fairness_score)

    # Warnings
    warnings = []
    if spread > 12:
        warnings.append("Sehr grosse Notenspreizung - bitte Extremwerte pruefen")
    if std_dev > 4:
        warnings.append("Hohe Streuung der Noten - moegliche Inkonsistenz")
    if len(outliers) > 2:
        warnings.append(f"{len(outliers)} Ausreisser erkannt - manuelle Pruefung empfohlen")
    if avg_grade < 5:
        warnings.append("Durchschnitt unter 5 Punkten - sind die Aufgaben angemessen?")
    if avg_grade > 12:
        warnings.append("Durchschnitt ueber 12 Punkten - Bewertungsmassstab pruefen")

    return {
        "klausur_id": klausur_id,
        "students_count": len(students),
        "graded_count": len(grades),
        "statistics": {
            "average_grade": round(avg_grade, 2),
            "average_raw_points": round(avg_raw, 2),
            "min_grade": min_grade,
            "max_grade": max_grade,
            "spread": spread,
            "standard_deviation": round(std_dev, 2)
        },
        "criteria_breakdown": criteria_averages,
        "outliers": outliers,
        "fairness_score": round(fairness_score),
        "warnings": warnings,
        "recommendation": "Bewertung konsistent" if fairness_score >= 70 else "Pruefung empfohlen"
    }


# =============================================
# AUDIT LOG ENDPOINTS
# =============================================

@router.get("/api/v1/audit-log")
async def get_audit_log(
    request: Request,
    entity_type: Optional[str] = None,
    entity_id: Optional[str] = None,
    limit: int = 100
):
    """Get audit log entries."""
    user = get_current_user(request)

    # Only admins can see full audit log
    if user.get("role") != "admin":
        # Regular users only see their own actions
        entries = [e for e in storage.audit_log_db if e.user_id == user["user_id"]]
    else:
        entries = storage.audit_log_db

    # Filter by entity
    if entity_type:
        entries = [e for e in entries if e.entity_type == entity_type]
    if entity_id:
        entries = [e for e in entries if e.entity_id == entity_id]

    # Sort by timestamp descending and limit
    entries = sorted(entries, key=lambda e: e.timestamp, reverse=True)[:limit]

    return [e.to_dict() for e in entries]


@router.get("/api/v1/students/{student_id}/audit-log")
async def get_student_audit_log(student_id: str, request: Request):
    """Get audit log for a specific student."""
    user = get_current_user(request)

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

    entries = [e for e in storage.audit_log_db if e.entity_id == student_id]
    entries = sorted(entries, key=lambda e: e.timestamp, reverse=True)

    return [e.to_dict() for e in entries]


# =============================================
# UTILITY ENDPOINTS
# =============================================

@router.get("/api/v1/grade-info")
async def get_grade_info():
    """Get grade thresholds and labels."""
    return {
        "thresholds": GRADE_THRESHOLDS,
        "labels": GRADE_LABELS,
        "criteria": DEFAULT_CRITERIA
    }


# =============================================
# SCHOOL CLASSES PROXY
# =============================================

@router.get("/api/school/classes")
async def get_school_classes(request: Request):
    """Proxy to school-service or return demo data."""
    try:
        auth_header = request.headers.get("Authorization", "")
        async with httpx.AsyncClient() as client:
            resp = await client.get(
                f"{SCHOOL_SERVICE_URL}/api/v1/school/classes",
                headers={"Authorization": auth_header},
                timeout=5.0
            )
            if resp.status_code == 200:
                return resp.json()
    except Exception as e:
        print(f"School service not available: {e}")

    # Return demo classes if school service unavailable
    return [
        {"id": "demo-q1", "name": "Q1 Deutsch GK", "student_count": 24},
        {"id": "demo-q2", "name": "Q2 Deutsch LK", "student_count": 18},
        {"id": "demo-q3", "name": "Q3 Deutsch GK", "student_count": 22},
        {"id": "demo-q4", "name": "Q4 Deutsch LK", "student_count": 15}
    ]


@router.get("/api/school/classes/{class_id}/students")
async def get_class_students(class_id: str, request: Request):
    """Proxy to school-service or return demo data."""
    try:
        auth_header = request.headers.get("Authorization", "")
        async with httpx.AsyncClient() as client:
            resp = await client.get(
                f"{SCHOOL_SERVICE_URL}/api/v1/school/classes/{class_id}/students",
                headers={"Authorization": auth_header},
                timeout=5.0
            )
            if resp.status_code == 200:
                return resp.json()
    except Exception as e:
        print(f"School service not available: {e}")

    # Return demo students
    demo_names = [
        "Anna Mueller", "Ben Schmidt", "Clara Weber", "David Fischer",
        "Emma Schneider", "Felix Wagner", "Greta Becker", "Hans Hoffmann",
        "Ida Schulz", "Jan Koch", "Katharina Bauer", "Leon Richter",
        "Maria Braun", "Niklas Lange", "Olivia Wolf", "Paul Krause"
    ]
    return [
        {"id": f"student-{i}", "name": name, "class_id": class_id}
        for i, name in enumerate(demo_names)
    ]
