"""
Letters API - Elternbrief-Verwaltung fuer BreakPilot.

Bietet Endpoints fuer:
- Speichern und Laden von Elternbriefen
- PDF-Export von Briefen
- Versenden per Email
- GFK-Integration fuer Textverbesserung

Split into:
- letters_models.py: Enums, Pydantic models, helper functions
- letters_api.py (this file): API endpoints and in-memory store
"""

import logging
import os
import uuid
from datetime import datetime
from typing import Optional, Dict, Any

from fastapi import APIRouter, HTTPException, Response, Query
import httpx

# PDF service requires WeasyPrint with system libraries - make optional for CI
try:
    from services.pdf_service import generate_letter_pdf, SchoolInfo
    _pdf_available = True
except (ImportError, OSError):
    generate_letter_pdf = None  # type: ignore
    SchoolInfo = None  # type: ignore
    _pdf_available = False

from .models import (
    LetterType,
    LetterTone,
    LetterStatus,
    LetterCreateRequest,
    LetterUpdateRequest,
    LetterResponse,
    LetterListResponse,
    ExportPDFRequest,
    ImproveRequest,
    ImproveResponse,
    SendEmailRequest,
    SendEmailResponse,
    get_type_label as _get_type_label,
    get_tone_label as _get_tone_label,
)

logger = logging.getLogger(__name__)

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


# =============================================================================
# In-Memory Storage (Prototyp - spaeter durch DB ersetzen)
# =============================================================================

_letters_store: Dict[str, Dict[str, Any]] = {}


def _get_letter(letter_id: str) -> Dict[str, Any]:
    """Holt Brief aus dem Store."""
    if letter_id not in _letters_store:
        raise HTTPException(status_code=404, detail=f"Brief mit ID {letter_id} nicht gefunden")
    return _letters_store[letter_id]


def _save_letter(letter_data: Dict[str, Any]) -> str:
    """Speichert Brief und gibt ID zurueck."""
    letter_id = letter_data.get("id") or str(uuid.uuid4())
    letter_data["id"] = letter_id
    letter_data["updated_at"] = datetime.now()
    if "created_at" not in letter_data:
        letter_data["created_at"] = datetime.now()
    _letters_store[letter_id] = letter_data
    return letter_id


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

@router.post("/", response_model=LetterResponse)
async def create_letter(request: LetterCreateRequest):
    """Erstellt einen neuen Elternbrief."""
    logger.info(f"Creating new letter for student: {request.student_name}")

    letter_data = {
        "recipient_name": request.recipient_name,
        "recipient_address": request.recipient_address,
        "student_name": request.student_name,
        "student_class": request.student_class,
        "subject": request.subject,
        "content": request.content,
        "letter_type": request.letter_type,
        "tone": request.tone,
        "teacher_name": request.teacher_name,
        "teacher_title": request.teacher_title,
        "school_info": request.school_info.model_dump() if request.school_info else None,
        "legal_references": [ref.model_dump() for ref in request.legal_references] if request.legal_references else None,
        "gfk_principles_applied": request.gfk_principles_applied,
        "gfk_score": None,
        "status": LetterStatus.DRAFT,
        "pdf_path": None,
        "dsms_cid": None,
        "sent_at": None,
    }

    letter_id = _save_letter(letter_data)
    letter_data["id"] = letter_id
    logger.info(f"Letter created with ID: {letter_id}")
    return LetterResponse(**letter_data)


# NOTE: Static routes must come BEFORE dynamic routes like /{letter_id}
@router.get("/types")
async def get_letter_types():
    """Gibt alle verfuegbaren Brieftypen zurueck."""
    return {"types": [{"value": t.value, "label": _get_type_label(t)} for t in LetterType]}


@router.get("/tones")
async def get_letter_tones():
    """Gibt alle verfuegbaren Tonalitaeten zurueck."""
    return {"tones": [{"value": t.value, "label": _get_tone_label(t)} for t in LetterTone]}


@router.get("/{letter_id}", response_model=LetterResponse)
async def get_letter(letter_id: str):
    """Laedt einen gespeicherten Brief."""
    logger.info(f"Getting letter: {letter_id}")
    letter_data = _get_letter(letter_id)
    return LetterResponse(**letter_data)


@router.get("/", response_model=LetterListResponse)
async def list_letters(
    student_id: Optional[str] = Query(None),
    class_name: Optional[str] = Query(None),
    letter_type: Optional[LetterType] = Query(None),
    status: Optional[LetterStatus] = Query(None),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100)
):
    """Listet alle gespeicherten Briefe mit optionalen Filtern."""
    logger.info("Listing letters with filters")

    filtered_letters = list(_letters_store.values())
    if class_name:
        filtered_letters = [l for l in filtered_letters if l.get("student_class") == class_name]
    if letter_type:
        filtered_letters = [l for l in filtered_letters if l.get("letter_type") == letter_type]
    if status:
        filtered_letters = [l for l in filtered_letters if l.get("status") == status]

    filtered_letters.sort(key=lambda x: x.get("created_at", datetime.min), reverse=True)
    total = len(filtered_letters)
    start = (page - 1) * page_size
    paginated_letters = filtered_letters[start:start + page_size]

    return LetterListResponse(
        letters=[LetterResponse(**l) for l in paginated_letters],
        total=total, page=page, page_size=page_size
    )


@router.put("/{letter_id}", response_model=LetterResponse)
async def update_letter(letter_id: str, request: LetterUpdateRequest):
    """Aktualisiert einen bestehenden Brief."""
    logger.info(f"Updating letter: {letter_id}")
    letter_data = _get_letter(letter_id)

    update_data = request.model_dump(exclude_unset=True)
    for key, value in update_data.items():
        if value is not None:
            if key == "school_info" and value:
                letter_data[key] = value if isinstance(value, dict) else value.model_dump()
            elif key == "legal_references" and value:
                letter_data[key] = [ref if isinstance(ref, dict) else ref.model_dump() for ref in value]
            else:
                letter_data[key] = value

    _save_letter(letter_data)
    return LetterResponse(**letter_data)


@router.delete("/{letter_id}")
async def delete_letter(letter_id: str):
    """Loescht einen Brief."""
    logger.info(f"Deleting letter: {letter_id}")
    if letter_id not in _letters_store:
        raise HTTPException(status_code=404, detail=f"Brief mit ID {letter_id} nicht gefunden")
    del _letters_store[letter_id]
    return {"message": f"Brief {letter_id} wurde geloescht"}


@router.post("/export-pdf")
async def export_letter_pdf(request: ExportPDFRequest):
    """Exportiert einen Brief als PDF."""
    logger.info("Exporting letter as PDF")

    if request.letter_id:
        letter_data = _get_letter(request.letter_id)
    elif request.letter_data:
        letter_data = request.letter_data.model_dump()
    else:
        raise HTTPException(status_code=400, detail="Entweder letter_id oder letter_data muss angegeben werden")

    if "date" not in letter_data:
        letter_data["date"] = datetime.now().strftime("%d.%m.%Y")

    try:
        pdf_bytes = generate_letter_pdf(letter_data)
    except Exception as e:
        logger.error(f"Error generating PDF: {e}")
        raise HTTPException(status_code=500, detail=f"Fehler bei PDF-Generierung: {str(e)}")

    student_name = letter_data.get("student_name", "Brief").replace(" ", "_")
    date_str = datetime.now().strftime("%Y%m%d")
    filename = f"Elternbrief_{student_name}_{date_str}.pdf"

    return Response(
        content=pdf_bytes, media_type="application/pdf",
        headers={"Content-Disposition": f"attachment; filename={filename}", "Content-Length": str(len(pdf_bytes))}
    )


@router.post("/{letter_id}/export-pdf")
async def export_saved_letter_pdf(letter_id: str):
    """Exportiert einen gespeicherten Brief als PDF (Kurzform)."""
    return await export_letter_pdf(ExportPDFRequest(letter_id=letter_id))


@router.post("/improve", response_model=ImproveResponse)
async def improve_letter_content(request: ImproveRequest):
    """Verbessert den Briefinhalt nach GFK-Prinzipien."""
    logger.info("Improving letter content with GFK principles")

    comm_service_url = os.getenv("COMMUNICATION_SERVICE_URL", "http://localhost:8000/v1/communication")

    try:
        async with httpx.AsyncClient() as client:
            validate_response = await client.post(
                f"{comm_service_url}/validate",
                json={"text": request.content}, timeout=30.0
            )

            if validate_response.status_code != 200:
                logger.warning(f"Validation service returned {validate_response.status_code}")
                return ImproveResponse(
                    improved_content=request.content,
                    changes=["Verbesserungsservice nicht verfuegbar"],
                    gfk_score=0.5, gfk_principles_applied=[]
                )

            validation_data = validate_response.json()

            if validation_data.get("is_valid", False) and validation_data.get("gfk_score", 0) > 0.8:
                return ImproveResponse(
                    improved_content=request.content,
                    changes=["Text entspricht bereits GFK-Standards"],
                    gfk_score=validation_data.get("gfk_score", 0.8),
                    gfk_principles_applied=validation_data.get("positive_elements", [])
                )

            return ImproveResponse(
                improved_content=request.content,
                changes=validation_data.get("suggestions", []),
                gfk_score=validation_data.get("gfk_score", 0.5),
                gfk_principles_applied=validation_data.get("positive_elements", [])
            )

    except httpx.TimeoutException:
        logger.error("Timeout while calling communication service")
        return ImproveResponse(
            improved_content=request.content,
            changes=["Zeitueberschreitung beim Verbesserungsservice"],
            gfk_score=0.5, gfk_principles_applied=[]
        )
    except Exception as e:
        logger.error(f"Error improving content: {e}")
        return ImproveResponse(
            improved_content=request.content,
            changes=[f"Fehler: {str(e)}"],
            gfk_score=0.5, gfk_principles_applied=[]
        )


@router.post("/{letter_id}/send", response_model=SendEmailResponse)
async def send_letter_email(letter_id: str, request: SendEmailRequest):
    """Versendet einen Brief per Email."""
    logger.info(f"Sending letter {letter_id} to {request.recipient_email}")
    letter_data = _get_letter(letter_id)

    try:
        pdf_attachment = None
        if request.include_pdf:
            letter_data["date"] = datetime.now().strftime("%d.%m.%Y")
            pdf_bytes = generate_letter_pdf(letter_data)
            pdf_attachment = {
                "filename": f"Elternbrief_{letter_data.get('student_name', 'Brief').replace(' ', '_')}.pdf",
                "content": pdf_bytes.hex(),
                "content_type": "application/pdf"
            }

        async with httpx.AsyncClient() as client:
            logger.info(f"Would send email: {letter_data.get('subject')} to {request.recipient_email}")
            letter_data["status"] = LetterStatus.SENT
            letter_data["sent_at"] = datetime.now()
            _save_letter(letter_data)

            return SendEmailResponse(
                success=True,
                message=f"Brief wurde an {request.recipient_email} gesendet",
                sent_at=datetime.now()
            )

    except Exception as e:
        logger.error(f"Error sending email: {e}")
        return SendEmailResponse(success=False, message=f"Fehler beim Versenden: {str(e)}", sent_at=None)


@router.get("/student/{student_id}", response_model=LetterListResponse)
async def get_letters_for_student(
    student_id: str,
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100)
):
    """Laedt alle Briefe fuer einen bestimmten Schueler."""
    logger.info(f"Getting letters for student: {student_id}")

    filtered_letters = [
        l for l in _letters_store.values()
        if student_id.lower() in l.get("student_name", "").lower()
    ]

    filtered_letters.sort(key=lambda x: x.get("created_at", datetime.min), reverse=True)
    total = len(filtered_letters)
    start = (page - 1) * page_size
    paginated_letters = filtered_letters[start:start + page_size]

    return LetterListResponse(
        letters=[LetterResponse(**l) for l in paginated_letters],
        total=total, page=page, page_size=page_size
    )
