"""
Certificates API - Zeugnisverwaltung fuer BreakPilot.

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

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

from fastapi import APIRouter, HTTPException, Response, Query

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

from .certificates_models import (
    CertificateType,
    CertificateStatus,
    BehaviorGrade,
    CertificateCreateRequest,
    CertificateUpdateRequest,
    CertificateResponse,
    CertificateListResponse,
    GradeStatistics,
    get_type_label as _get_type_label,
    calculate_average as _calculate_average,
)

logger = logging.getLogger(__name__)

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


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

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


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


def _save_certificate(cert_data: Dict[str, Any]) -> str:
    """Speichert Zeugnis und gibt ID zurueck."""
    cert_id = cert_data.get("id") or str(uuid.uuid4())
    cert_data["id"] = cert_id
    cert_data["updated_at"] = datetime.now()
    if "created_at" not in cert_data:
        cert_data["created_at"] = datetime.now()
    _certificates_store[cert_id] = cert_data
    return cert_id


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

@router.post("/", response_model=CertificateResponse)
async def create_certificate(request: CertificateCreateRequest):
    """Erstellt ein neues Zeugnis."""
    logger.info(f"Creating new certificate for student: {request.student_name}")

    subjects_list = [s.model_dump() for s in request.subjects]

    cert_data = {
        "student_id": request.student_id,
        "student_name": request.student_name,
        "student_birthdate": request.student_birthdate,
        "student_class": request.student_class,
        "school_year": request.school_year,
        "certificate_type": request.certificate_type,
        "subjects": subjects_list,
        "attendance": request.attendance.model_dump(),
        "remarks": request.remarks,
        "class_teacher": request.class_teacher,
        "principal": request.principal,
        "school_info": request.school_info.model_dump() if request.school_info else None,
        "issue_date": request.issue_date or datetime.now().strftime("%d.%m.%Y"),
        "social_behavior": request.social_behavior,
        "work_behavior": request.work_behavior,
        "status": CertificateStatus.DRAFT,
        "average_grade": _calculate_average(subjects_list),
        "pdf_path": None,
        "dsms_cid": None,
    }

    cert_id = _save_certificate(cert_data)
    cert_data["id"] = cert_id
    logger.info(f"Certificate created with ID: {cert_id}")
    return CertificateResponse(**cert_data)


# IMPORTANT: Static routes must be defined BEFORE dynamic /{cert_id} route
@router.get("/types")
async def get_certificate_types():
    """Gibt alle verfuegbaren Zeugnistypen zurueck."""
    return {"types": [{"value": t.value, "label": _get_type_label(t)} for t in CertificateType]}


@router.get("/behavior-grades")
async def get_behavior_grades():
    """Gibt alle verfuegbaren Verhaltensnoten zurueck."""
    labels = {
        BehaviorGrade.A: "A - Sehr gut", BehaviorGrade.B: "B - Gut",
        BehaviorGrade.C: "C - Befriedigend", BehaviorGrade.D: "D - Verbesserungswuerdig"
    }
    return {"grades": [{"value": g.value, "label": labels[g]} for g in BehaviorGrade]}


@router.get("/{cert_id}", response_model=CertificateResponse)
async def get_certificate(cert_id: str):
    """Laedt ein gespeichertes Zeugnis."""
    logger.info(f"Getting certificate: {cert_id}")
    return CertificateResponse(**_get_certificate(cert_id))


@router.get("/", response_model=CertificateListResponse)
async def list_certificates(
    student_id: Optional[str] = Query(None),
    class_name: Optional[str] = Query(None),
    school_year: Optional[str] = Query(None),
    certificate_type: Optional[CertificateType] = Query(None),
    status: Optional[CertificateStatus] = Query(None),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100)
):
    """Listet alle gespeicherten Zeugnisse mit optionalen Filtern."""
    logger.info("Listing certificates with filters")

    filtered_certs = list(_certificates_store.values())
    if student_id:
        filtered_certs = [c for c in filtered_certs if c.get("student_id") == student_id]
    if class_name:
        filtered_certs = [c for c in filtered_certs if c.get("student_class") == class_name]
    if school_year:
        filtered_certs = [c for c in filtered_certs if c.get("school_year") == school_year]
    if certificate_type:
        filtered_certs = [c for c in filtered_certs if c.get("certificate_type") == certificate_type]
    if status:
        filtered_certs = [c for c in filtered_certs if c.get("status") == status]

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

    return CertificateListResponse(
        certificates=[CertificateResponse(**c) for c in paginated_certs],
        total=total, page=page, page_size=page_size
    )


@router.put("/{cert_id}", response_model=CertificateResponse)
async def update_certificate(cert_id: str, request: CertificateUpdateRequest):
    """Aktualisiert ein bestehendes Zeugnis."""
    logger.info(f"Updating certificate: {cert_id}")
    cert_data = _get_certificate(cert_id)

    if cert_data.get("status") in [CertificateStatus.ISSUED, CertificateStatus.ARCHIVED]:
        raise HTTPException(status_code=400, detail="Zeugnis wurde bereits ausgestellt und kann nicht mehr bearbeitet werden")

    update_data = request.model_dump(exclude_unset=True)
    for key, value in update_data.items():
        if value is not None:
            if key == "subjects":
                cert_data[key] = [s if isinstance(s, dict) else s.model_dump() for s in value]
                cert_data["average_grade"] = _calculate_average(cert_data["subjects"])
            elif key == "attendance":
                cert_data[key] = value if isinstance(value, dict) else value.model_dump()
            else:
                cert_data[key] = value

    _save_certificate(cert_data)
    return CertificateResponse(**cert_data)


@router.delete("/{cert_id}")
async def delete_certificate(cert_id: str):
    """Loescht ein Zeugnis. Nur Entwuerfe koennen geloescht werden."""
    logger.info(f"Deleting certificate: {cert_id}")
    cert_data = _get_certificate(cert_id)
    if cert_data.get("status") != CertificateStatus.DRAFT:
        raise HTTPException(status_code=400, detail="Nur Zeugnis-Entwuerfe koennen geloescht werden")
    del _certificates_store[cert_id]
    return {"message": f"Zeugnis {cert_id} wurde geloescht"}


@router.post("/{cert_id}/export-pdf")
async def export_certificate_pdf(cert_id: str):
    """Exportiert ein Zeugnis als PDF."""
    logger.info(f"Exporting certificate {cert_id} as PDF")
    cert_data = _get_certificate(cert_id)

    try:
        pdf_bytes = generate_certificate_pdf(cert_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 = cert_data.get("student_name", "Zeugnis").replace(" ", "_")
    school_year = cert_data.get("school_year", "").replace("/", "-")
    cert_type = cert_data.get("certificate_type", "zeugnis")
    filename = f"Zeugnis_{student_name}_{cert_type}_{school_year}.pdf"

    from urllib.parse import quote
    filename_ascii = filename.encode('ascii', 'replace').decode('ascii')
    filename_encoded = quote(filename, safe='')

    return Response(
        content=pdf_bytes, media_type="application/pdf",
        headers={
            "Content-Disposition": f"attachment; filename=\"{filename_ascii}\"; filename*=UTF-8''{filename_encoded}",
            "Content-Length": str(len(pdf_bytes))
        }
    )


@router.post("/{cert_id}/submit-review")
async def submit_for_review(cert_id: str):
    """Reicht Zeugnis zur Pruefung ein."""
    logger.info(f"Submitting certificate {cert_id} for review")
    cert_data = _get_certificate(cert_id)
    if cert_data.get("status") != CertificateStatus.DRAFT:
        raise HTTPException(status_code=400, detail="Nur Entwuerfe koennen zur Pruefung eingereicht werden")
    if not cert_data.get("subjects"):
        raise HTTPException(status_code=400, detail="Keine Fachnoten eingetragen")
    cert_data["status"] = CertificateStatus.REVIEW
    _save_certificate(cert_data)
    return {"message": "Zeugnis wurde zur Pruefung eingereicht", "status": CertificateStatus.REVIEW}


@router.post("/{cert_id}/approve")
async def approve_certificate(cert_id: str):
    """Genehmigt ein Zeugnis."""
    logger.info(f"Approving certificate {cert_id}")
    cert_data = _get_certificate(cert_id)
    if cert_data.get("status") != CertificateStatus.REVIEW:
        raise HTTPException(status_code=400, detail="Nur Zeugnisse in Pruefung koennen genehmigt werden")
    cert_data["status"] = CertificateStatus.APPROVED
    _save_certificate(cert_data)
    return {"message": "Zeugnis wurde genehmigt", "status": CertificateStatus.APPROVED}


@router.post("/{cert_id}/issue")
async def issue_certificate(cert_id: str):
    """Stellt ein Zeugnis offiziell aus."""
    logger.info(f"Issuing certificate {cert_id}")
    cert_data = _get_certificate(cert_id)
    if cert_data.get("status") != CertificateStatus.APPROVED:
        raise HTTPException(status_code=400, detail="Nur genehmigte Zeugnisse koennen ausgestellt werden")
    cert_data["status"] = CertificateStatus.ISSUED
    cert_data["issue_date"] = datetime.now().strftime("%d.%m.%Y")
    _save_certificate(cert_data)
    return {"message": "Zeugnis wurde ausgestellt", "status": CertificateStatus.ISSUED, "issue_date": cert_data["issue_date"]}


@router.get("/student/{student_id}", response_model=CertificateListResponse)
async def get_certificates_for_student(
    student_id: str, page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100)
):
    """Laedt alle Zeugnisse fuer einen bestimmten Schueler."""
    logger.info(f"Getting certificates for student: {student_id}")
    filtered_certs = [c for c in _certificates_store.values() if c.get("student_id") == student_id]
    filtered_certs.sort(key=lambda x: (x.get("school_year", ""), x.get("certificate_type", "")), reverse=True)
    total = len(filtered_certs)
    start = (page - 1) * page_size
    paginated_certs = filtered_certs[start:start + page_size]
    return CertificateListResponse(
        certificates=[CertificateResponse(**c) for c in paginated_certs],
        total=total, page=page, page_size=page_size
    )


@router.get("/class/{class_name}/statistics", response_model=GradeStatistics)
async def get_class_statistics(
    class_name: str,
    school_year: str = Query(..., description="Schuljahr"),
    certificate_type: CertificateType = Query(CertificateType.HALBJAHR)
):
    """Berechnet Notenstatistiken fuer eine Klasse."""
    logger.info(f"Calculating statistics for class {class_name}")

    class_certs = [
        c for c in _certificates_store.values()
        if c.get("student_class") == class_name
        and c.get("school_year") == school_year
        and c.get("certificate_type") == certificate_type
    ]

    if not class_certs:
        raise HTTPException(status_code=404, detail=f"Keine Zeugnisse fuer Klasse {class_name} im Schuljahr {school_year} gefunden")

    all_grades: List[float] = []
    subject_grades: Dict[str, List[float]] = {}
    grade_counts = {"1": 0, "2": 0, "3": 0, "4": 0, "5": 0, "6": 0}

    for cert in class_certs:
        avg = cert.get("average_grade")
        if avg:
            all_grades.append(avg)
            rounded = str(round(avg))
            if rounded in grade_counts:
                grade_counts[rounded] += 1

        for subject in cert.get("subjects", []):
            name = subject.get("name")
            grade_str = subject.get("grade")
            try:
                grade = float(grade_str)
                if name not in subject_grades:
                    subject_grades[name] = []
                subject_grades[name].append(grade)
            except (ValueError, TypeError):
                pass

    subject_averages = {
        name: round(sum(grades) / len(grades), 2)
        for name, grades in subject_grades.items() if grades
    }

    return GradeStatistics(
        class_name=class_name, school_year=school_year,
        certificate_type=certificate_type, student_count=len(class_certs),
        average_grade=round(sum(all_grades) / len(all_grades), 2) if all_grades else 0.0,
        grade_distribution=grade_counts, subject_averages=subject_averages
    )
