"""
Worksheets API - REST API für Arbeitsblatt-Generierung.

Integriert alle Content-Generatoren:
- Multiple Choice Questions
- Lückentexte (Cloze)
- Mindmaps
- Quizze (True/False, Matching, Sorting, Open)

Unterstützt:
- H5P-Export für interaktive Inhalte
- PDF-Export für Druckversionen
- JSON-Export für Frontend-Integration
"""

import logging
import uuid
from datetime import datetime
from typing import Dict

from fastapi import APIRouter, HTTPException

from generators import (
    MultipleChoiceGenerator,
    ClozeGenerator,
    MindmapGenerator,
    QuizGenerator
)

from .models import (
    ContentType,
    GenerateRequest,
    MCGenerateRequest,
    ClozeGenerateRequest,
    MindmapGenerateRequest,
    QuizGenerateRequest,
    BatchGenerateRequest,
    WorksheetContent,
    GenerateResponse,
    BatchGenerateResponse,
    parse_difficulty,
    parse_cloze_type,
    parse_quiz_types,
)

logger = logging.getLogger(__name__)

router = APIRouter(
    prefix="/worksheets",
    tags=["worksheets"],
)


# ============================================================================
# In-Memory Storage (später durch DB ersetzen)
# ============================================================================

_generated_content: Dict[str, WorksheetContent] = {}


# ============================================================================
# Generator Instances
# ============================================================================

mc_generator = MultipleChoiceGenerator()
cloze_generator = ClozeGenerator()
mindmap_generator = MindmapGenerator()
quiz_generator = QuizGenerator()


def _store_content(content: WorksheetContent) -> None:
    """Speichert generierten Content."""
    _generated_content[content.id] = content


# ============================================================================
# API Endpoints
# ============================================================================

@router.post("/generate/multiple-choice", response_model=GenerateResponse)
async def generate_multiple_choice(request: MCGenerateRequest):
    """Generiert Multiple-Choice-Fragen aus Quelltext."""
    try:
        difficulty = parse_difficulty(request.difficulty)

        questions = mc_generator.generate(
            source_text=request.source_text,
            num_questions=request.num_questions,
            difficulty=difficulty,
            subject=request.subject,
            grade_level=request.grade_level
        )

        if not questions:
            return GenerateResponse(
                success=False,
                error="Keine Fragen generiert. Text möglicherweise zu kurz."
            )

        questions_dict = mc_generator.to_dict(questions)
        h5p_format = mc_generator.to_h5p_format(questions)

        content = WorksheetContent(
            id=str(uuid.uuid4()),
            content_type=ContentType.MULTIPLE_CHOICE.value,
            data={"questions": questions_dict},
            h5p_format=h5p_format,
            created_at=datetime.utcnow(),
            topic=request.topic,
            difficulty=request.difficulty
        )

        _store_content(content)
        return GenerateResponse(success=True, content=content)

    except Exception as e:
        logger.error(f"Error generating MC questions: {e}")
        return GenerateResponse(success=False, error=str(e))


@router.post("/generate/cloze", response_model=GenerateResponse)
async def generate_cloze(request: ClozeGenerateRequest):
    """Generiert Lückentext aus Quelltext."""
    try:
        cloze_type = parse_cloze_type(request.cloze_type)

        cloze = cloze_generator.generate(
            source_text=request.source_text,
            num_gaps=request.num_gaps,
            difficulty=request.difficulty,
            cloze_type=cloze_type,
            topic=request.topic
        )

        if not cloze.gaps:
            return GenerateResponse(
                success=False,
                error="Keine Lücken generiert. Text möglicherweise zu kurz."
            )

        cloze_dict = cloze_generator.to_dict(cloze)
        h5p_format = cloze_generator.to_h5p_format(cloze)

        content = WorksheetContent(
            id=str(uuid.uuid4()),
            content_type=ContentType.CLOZE.value,
            data=cloze_dict,
            h5p_format=h5p_format,
            created_at=datetime.utcnow(),
            topic=request.topic,
            difficulty=request.difficulty
        )

        _store_content(content)
        return GenerateResponse(success=True, content=content)

    except Exception as e:
        logger.error(f"Error generating cloze: {e}")
        return GenerateResponse(success=False, error=str(e))


@router.post("/generate/mindmap", response_model=GenerateResponse)
async def generate_mindmap(request: MindmapGenerateRequest):
    """Generiert Mindmap aus Quelltext."""
    try:
        mindmap = mindmap_generator.generate(
            source_text=request.source_text,
            title=request.topic,
            max_depth=request.max_depth,
            topic=request.topic
        )

        if mindmap.total_nodes <= 1:
            return GenerateResponse(
                success=False,
                error="Mindmap konnte nicht generiert werden. Text möglicherweise zu kurz."
            )

        mindmap_dict = mindmap_generator.to_dict(mindmap)
        mermaid = mindmap_generator.to_mermaid(mindmap)
        json_tree = mindmap_generator.to_json_tree(mindmap)

        content = WorksheetContent(
            id=str(uuid.uuid4()),
            content_type=ContentType.MINDMAP.value,
            data={
                "mindmap": mindmap_dict,
                "mermaid": mermaid,
                "json_tree": json_tree
            },
            h5p_format=None,
            created_at=datetime.utcnow(),
            topic=request.topic,
            difficulty=None
        )

        _store_content(content)
        return GenerateResponse(success=True, content=content)

    except Exception as e:
        logger.error(f"Error generating mindmap: {e}")
        return GenerateResponse(success=False, error=str(e))


@router.post("/generate/quiz", response_model=GenerateResponse)
async def generate_quiz(request: QuizGenerateRequest):
    """Generiert Quiz mit verschiedenen Fragetypen."""
    try:
        quiz_types = parse_quiz_types(request.quiz_types)

        all_questions = []
        quizzes = []

        for quiz_type in quiz_types:
            quiz = quiz_generator.generate(
                source_text=request.source_text,
                quiz_type=quiz_type,
                num_questions=request.num_items,
                difficulty=request.difficulty,
                topic=request.topic
            )
            quizzes.append(quiz)
            all_questions.extend(quiz.questions)

        if len(all_questions) == 0:
            return GenerateResponse(
                success=False,
                error="Quiz konnte nicht generiert werden. Text möglicherweise zu kurz."
            )

        combined_quiz_dict = {
            "quiz_types": [qt.value for qt in quiz_types],
            "title": f"Combined Quiz - {request.topic or 'Various Topics'}",
            "topic": request.topic,
            "difficulty": request.difficulty,
            "questions": []
        }

        for quiz in quizzes:
            quiz_dict = quiz_generator.to_dict(quiz)
            combined_quiz_dict["questions"].extend(quiz_dict.get("questions", []))

        h5p_format = quiz_generator.to_h5p_format(quizzes[0]) if quizzes else {}

        content = WorksheetContent(
            id=str(uuid.uuid4()),
            content_type=ContentType.QUIZ.value,
            data=combined_quiz_dict,
            h5p_format=h5p_format,
            created_at=datetime.utcnow(),
            topic=request.topic,
            difficulty=request.difficulty
        )

        _store_content(content)
        return GenerateResponse(success=True, content=content)

    except Exception as e:
        logger.error(f"Error generating quiz: {e}")
        return GenerateResponse(success=False, error=str(e))


@router.post("/generate/batch", response_model=BatchGenerateResponse)
async def generate_batch(request: BatchGenerateRequest):
    """Generiert mehrere Content-Typen aus einem Quelltext."""
    contents = []
    errors = []

    for content_type in request.content_types:
        try:
            if content_type == "multiple_choice":
                mc_req = MCGenerateRequest(
                    source_text=request.source_text,
                    topic=request.topic,
                    subject=request.subject,
                    grade_level=request.grade_level,
                    difficulty=request.difficulty
                )
                result = await generate_multiple_choice(mc_req)

            elif content_type == "cloze":
                cloze_req = ClozeGenerateRequest(
                    source_text=request.source_text,
                    topic=request.topic,
                    subject=request.subject,
                    grade_level=request.grade_level,
                    difficulty=request.difficulty
                )
                result = await generate_cloze(cloze_req)

            elif content_type == "mindmap":
                mindmap_req = MindmapGenerateRequest(
                    source_text=request.source_text,
                    topic=request.topic,
                    subject=request.subject,
                    grade_level=request.grade_level
                )
                result = await generate_mindmap(mindmap_req)

            elif content_type == "quiz":
                quiz_req = QuizGenerateRequest(
                    source_text=request.source_text,
                    topic=request.topic,
                    subject=request.subject,
                    grade_level=request.grade_level,
                    difficulty=request.difficulty
                )
                result = await generate_quiz(quiz_req)

            else:
                errors.append(f"Unbekannter Content-Typ: {content_type}")
                continue

            if result.success and result.content:
                contents.append(result.content)
            elif result.error:
                errors.append(f"{content_type}: {result.error}")

        except Exception as e:
            errors.append(f"{content_type}: {str(e)}")

    return BatchGenerateResponse(
        success=len(contents) > 0,
        contents=contents,
        errors=errors
    )


@router.get("/content/{content_id}", response_model=GenerateResponse)
async def get_content(content_id: str):
    """Ruft gespeicherten Content ab."""
    content = _generated_content.get(content_id)

    if not content:
        raise HTTPException(status_code=404, detail="Content nicht gefunden")

    return GenerateResponse(success=True, content=content)


@router.get("/content/{content_id}/h5p")
async def get_content_h5p(content_id: str):
    """Gibt H5P-Format für Content zurück."""
    content = _generated_content.get(content_id)

    if not content:
        raise HTTPException(status_code=404, detail="Content nicht gefunden")

    if not content.h5p_format:
        raise HTTPException(
            status_code=400,
            detail="H5P-Format für diesen Content-Typ nicht verfügbar"
        )

    return content.h5p_format


@router.delete("/content/{content_id}")
async def delete_content(content_id: str):
    """Löscht gespeicherten Content."""
    if content_id not in _generated_content:
        raise HTTPException(status_code=404, detail="Content nicht gefunden")

    del _generated_content[content_id]
    return {"status": "deleted", "id": content_id}


@router.get("/types")
async def list_content_types():
    """Listet verfügbare Content-Typen und deren Optionen."""
    return {
        "content_types": [
            {
                "type": "multiple_choice",
                "name": "Multiple Choice",
                "description": "Fragen mit 4 Antwortmöglichkeiten",
                "options": {
                    "num_questions": {"min": 1, "max": 20, "default": 5},
                    "difficulty": ["easy", "medium", "hard"]
                },
                "h5p_supported": True
            },
            {
                "type": "cloze",
                "name": "Lückentext",
                "description": "Text mit ausgeblendeten Schlüsselwörtern",
                "options": {
                    "num_gaps": {"min": 1, "max": 15, "default": 5},
                    "difficulty": ["easy", "medium", "hard"],
                    "cloze_type": ["fill_in", "drag_drop", "dropdown"]
                },
                "h5p_supported": True
            },
            {
                "type": "mindmap",
                "name": "Mindmap",
                "description": "Hierarchische Struktur aus Hauptthema und Unterthemen",
                "options": {
                    "max_depth": {"min": 2, "max": 5, "default": 3}
                },
                "h5p_supported": False,
                "export_formats": ["mermaid", "json_tree"]
            },
            {
                "type": "quiz",
                "name": "Quiz",
                "description": "Verschiedene Fragetypen kombiniert",
                "options": {
                    "quiz_types": ["true_false", "matching", "sorting", "open_ended"],
                    "num_items": {"min": 1, "max": 10, "default": 5},
                    "difficulty": ["easy", "medium", "hard"]
                },
                "h5p_supported": True
            }
        ]
    }


@router.get("/history")
async def get_generation_history(limit: int = 10):
    """Gibt die letzten generierten Contents zurück."""
    sorted_contents = sorted(
        _generated_content.values(),
        key=lambda x: x.created_at,
        reverse=True
    )

    return {
        "total": len(_generated_content),
        "contents": [
            {
                "id": c.id,
                "content_type": c.content_type,
                "topic": c.topic,
                "difficulty": c.difficulty,
                "created_at": c.created_at.isoformat()
            }
            for c in sorted_contents[:limit]
        ]
    }
