"""
Classroom API - Analytics & Reflections Endpoints.

Endpoints fuer Session-Analytics und Post-Lesson Reflections (Phase 5).
"""

from uuid import uuid4
from typing import Dict, List, Optional, Any
from datetime import datetime, timedelta
import logging

from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel, Field

from .shared import init_db_if_needed, DB_ENABLED, logger

try:
    from classroom_engine.database import SessionLocal
    from classroom_engine.repository import AnalyticsRepository, ReflectionRepository
    from classroom_engine.analytics import LessonReflection
except ImportError:
    pass

router = APIRouter(tags=["Analytics"])


# === Pydantic Models ===

class SessionSummaryResponse(BaseModel):
    """Response fuer Session-Summary."""
    session_id: str
    teacher_id: str
    class_id: str
    subject: str
    topic: Optional[str]
    date: Optional[str]
    date_formatted: str
    total_duration_seconds: int
    total_duration_formatted: str
    planned_duration_seconds: int
    planned_duration_formatted: str
    phases_completed: int
    total_phases: int
    completion_percentage: int
    phase_statistics: List[Dict[str, Any]]
    total_overtime_seconds: int
    total_overtime_formatted: str
    phases_with_overtime: int
    total_pause_count: int
    total_pause_seconds: int
    reflection_notes: str = ""
    reflection_rating: Optional[int] = None
    key_learnings: List[str] = []


class TeacherAnalyticsResponse(BaseModel):
    """Response fuer Lehrer-Analytics."""
    teacher_id: str
    period_start: Optional[str]
    period_end: Optional[str]
    total_sessions: int
    completed_sessions: int
    total_teaching_minutes: int
    total_teaching_hours: float
    avg_phase_durations: Dict[str, int]
    sessions_with_overtime: int
    overtime_percentage: int
    avg_overtime_seconds: int
    avg_overtime_formatted: str
    most_overtime_phase: Optional[str]
    avg_pause_count: float
    avg_pause_duration_seconds: int
    subjects_taught: Dict[str, int]
    classes_taught: Dict[str, int]


class ReflectionCreate(BaseModel):
    """Request-Body fuer Reflection-Erstellung."""
    session_id: str
    teacher_id: str
    notes: str = ""
    overall_rating: Optional[int] = Field(None, ge=1, le=5)
    what_worked: List[str] = []
    improvements: List[str] = []
    notes_for_next_lesson: str = ""


class ReflectionUpdate(BaseModel):
    """Request-Body fuer Reflection-Update."""
    notes: Optional[str] = None
    overall_rating: Optional[int] = Field(None, ge=1, le=5)
    what_worked: Optional[List[str]] = None
    improvements: Optional[List[str]] = None
    notes_for_next_lesson: Optional[str] = None


class ReflectionResponse(BaseModel):
    """Response fuer eine einzelne Reflection."""
    reflection_id: str
    session_id: str
    teacher_id: str
    notes: str
    overall_rating: Optional[int]
    what_worked: List[str]
    improvements: List[str]
    notes_for_next_lesson: str
    created_at: Optional[str]
    updated_at: Optional[str]


class ReflectionListResponse(BaseModel):
    """Response fuer Reflection-Liste."""
    reflections: List[ReflectionResponse]
    total: int


# === Analytics Endpoints ===

@router.get("/analytics/session/{session_id}")
async def get_session_summary(session_id: str) -> SessionSummaryResponse:
    """Gibt die Analytics-Zusammenfassung einer Session zurueck."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = AnalyticsRepository(db)
        summary = repo.get_session_summary(session_id)

        if not summary:
            raise HTTPException(status_code=404, detail=f"Session {session_id} not found")

        return SessionSummaryResponse(**summary.to_dict())


@router.get("/analytics/teacher/{teacher_id}")
async def get_teacher_analytics(
    teacher_id: str,
    days: int = Query(30, ge=1, le=365)
) -> TeacherAnalyticsResponse:
    """Gibt aggregierte Analytics fuer einen Lehrer zurueck."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    period_end = datetime.utcnow()
    period_start = period_end - timedelta(days=days)

    with SessionLocal() as db:
        repo = AnalyticsRepository(db)
        analytics = repo.get_teacher_analytics(teacher_id, period_start, period_end)

        return TeacherAnalyticsResponse(**analytics.to_dict())


@router.get("/analytics/phase-trends/{teacher_id}/{phase}")
async def get_phase_trends(
    teacher_id: str,
    phase: str,
    limit: int = Query(20, ge=1, le=100)
) -> Dict[str, Any]:
    """Gibt die Dauer-Trends fuer eine Phase zurueck."""
    if phase not in ["einstieg", "erarbeitung", "sicherung", "transfer", "reflexion"]:
        raise HTTPException(status_code=400, detail=f"Invalid phase: {phase}")

    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = AnalyticsRepository(db)
        trends = repo.get_phase_duration_trends(teacher_id, phase, limit)

        return {
            "teacher_id": teacher_id,
            "phase": phase,
            "data_points": trends,
            "count": len(trends)
        }


@router.get("/analytics/overtime/{teacher_id}")
async def get_overtime_analysis(
    teacher_id: str,
    limit: int = Query(30, ge=1, le=100)
) -> Dict[str, Any]:
    """Analysiert Overtime-Muster nach Phase."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = AnalyticsRepository(db)
        analysis = repo.get_overtime_analysis(teacher_id, limit)

        return {
            "teacher_id": teacher_id,
            "sessions_analyzed": limit,
            "phases": analysis
        }


# === Reflection Endpoints ===

@router.post("/reflections", status_code=201)
async def create_reflection(data: ReflectionCreate) -> ReflectionResponse:
    """Erstellt eine Post-Lesson Reflection."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = ReflectionRepository(db)

        existing = repo.get_by_session(data.session_id)
        if existing:
            raise HTTPException(
                status_code=409,
                detail=f"Reflection for session {data.session_id} already exists"
            )

        reflection = LessonReflection(
            reflection_id=str(uuid4()),
            session_id=data.session_id,
            teacher_id=data.teacher_id,
            notes=data.notes,
            overall_rating=data.overall_rating,
            what_worked=data.what_worked,
            improvements=data.improvements,
            notes_for_next_lesson=data.notes_for_next_lesson,
            created_at=datetime.utcnow(),
        )

        db_reflection = repo.create(reflection)
        result = repo.to_dataclass(db_reflection)

        return ReflectionResponse(**result.to_dict())


@router.get("/reflections/session/{session_id}")
async def get_reflection_by_session(session_id: str) -> ReflectionResponse:
    """Holt die Reflection einer Session."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = ReflectionRepository(db)
        db_reflection = repo.get_by_session(session_id)

        if not db_reflection:
            raise HTTPException(status_code=404, detail=f"No reflection for session {session_id}")

        result = repo.to_dataclass(db_reflection)
        return ReflectionResponse(**result.to_dict())


@router.get("/reflections/teacher/{teacher_id}")
async def get_reflections_by_teacher(
    teacher_id: str,
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0)
) -> ReflectionListResponse:
    """Holt alle Reflections eines Lehrers."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = ReflectionRepository(db)
        db_reflections = repo.get_by_teacher(teacher_id, limit, offset)

        reflections = []
        for db_ref in db_reflections:
            result = repo.to_dataclass(db_ref)
            reflections.append(ReflectionResponse(**result.to_dict()))

        total = repo.count_by_teacher(teacher_id)

        return ReflectionListResponse(reflections=reflections, total=total)


@router.put("/reflections/{reflection_id}")
async def update_reflection(reflection_id: str, data: ReflectionUpdate) -> ReflectionResponse:
    """Aktualisiert eine Reflection."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = ReflectionRepository(db)
        db_reflection = repo.get_by_id(reflection_id)

        if not db_reflection:
            raise HTTPException(status_code=404, detail=f"Reflection {reflection_id} not found")

        reflection = repo.to_dataclass(db_reflection)

        if data.notes is not None:
            reflection.notes = data.notes
        if data.overall_rating is not None:
            reflection.overall_rating = data.overall_rating
        if data.what_worked is not None:
            reflection.what_worked = data.what_worked
        if data.improvements is not None:
            reflection.improvements = data.improvements
        if data.notes_for_next_lesson is not None:
            reflection.notes_for_next_lesson = data.notes_for_next_lesson

        reflection.updated_at = datetime.utcnow()

        db_reflection = repo.update(reflection)
        result = repo.to_dataclass(db_reflection)

        return ReflectionResponse(**result.to_dict())


@router.delete("/reflections/{reflection_id}")
async def delete_reflection(reflection_id: str) -> Dict[str, str]:
    """Loescht eine Reflection."""
    if not DB_ENABLED:
        raise HTTPException(status_code=503, detail="Database not available")

    init_db_if_needed()

    with SessionLocal() as db:
        repo = ReflectionRepository(db)
        db_reflection = repo.get_by_id(reflection_id)

        if not db_reflection:
            raise HTTPException(status_code=404, detail=f"Reflection {reflection_id} not found")

        repo.delete(reflection_id)

        return {"status": "deleted", "reflection_id": reflection_id}
