"""
API Routes fuer Alert Digests (Wochenzusammenfassungen).

Endpoints:
- GET /digests - Liste aller Digests fuer den User
- GET /digests/{id} - Digest-Details
- GET /digests/{id}/pdf - PDF-Download
- POST /digests/generate - Digest manuell generieren
- POST /digests/{id}/send-email - Digest per E-Mail versenden
"""

import io
from datetime import datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session as DBSession

from ..db.database import get_db
from ..db.models import (
    AlertDigestDB, UserAlertSubscriptionDB, DigestStatusEnum
)
from ..processing.digest_generator import DigestGenerator
from .digests_models import (
    DigestDetail,
    DigestListResponse,
    GenerateDigestRequest,
    GenerateDigestResponse,
    SendEmailRequest,
    SendEmailResponse,
    digest_to_list_item,
    digest_to_detail,
)
from .digests_email import generate_pdf_from_html, send_digest_by_email


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


def get_user_id_from_request() -> str:
    """Extrahiert User-ID aus Request. TODO: JWT-Token auswerten."""
    return "demo-user"


# ============================================================================
# Endpoints
# ============================================================================

@router.get("", response_model=DigestListResponse)
async def list_digests(
    limit: int = Query(10, ge=1, le=50),
    offset: int = Query(0, ge=0),
    db: DBSession = Depends(get_db)
):
    """Liste alle Digests des aktuellen Users."""
    user_id = get_user_id_from_request()

    query = db.query(AlertDigestDB).filter(
        AlertDigestDB.user_id == user_id
    ).order_by(AlertDigestDB.created_at.desc())

    total = query.count()
    digests = query.offset(offset).limit(limit).all()

    return DigestListResponse(
        digests=[digest_to_list_item(d) for d in digests],
        total=total
    )


@router.get("/latest", response_model=DigestDetail)
async def get_latest_digest(db: DBSession = Depends(get_db)):
    """Hole den neuesten Digest des Users."""
    user_id = get_user_id_from_request()

    digest = db.query(AlertDigestDB).filter(
        AlertDigestDB.user_id == user_id
    ).order_by(AlertDigestDB.created_at.desc()).first()

    if not digest:
        raise HTTPException(status_code=404, detail="Kein Digest vorhanden")

    return digest_to_detail(digest)


@router.get("/{digest_id}", response_model=DigestDetail)
async def get_digest(digest_id: str, db: DBSession = Depends(get_db)):
    """Hole Details eines spezifischen Digests."""
    user_id = get_user_id_from_request()

    digest = db.query(AlertDigestDB).filter(
        AlertDigestDB.id == digest_id,
        AlertDigestDB.user_id == user_id
    ).first()

    if not digest:
        raise HTTPException(status_code=404, detail="Digest nicht gefunden")

    return digest_to_detail(digest)


@router.get("/{digest_id}/pdf")
async def get_digest_pdf(digest_id: str, db: DBSession = Depends(get_db)):
    """Generiere und lade PDF-Version des Digests herunter."""
    user_id = get_user_id_from_request()

    digest = db.query(AlertDigestDB).filter(
        AlertDigestDB.id == digest_id,
        AlertDigestDB.user_id == user_id
    ).first()

    if not digest:
        raise HTTPException(status_code=404, detail="Digest nicht gefunden")
    if not digest.summary_html:
        raise HTTPException(status_code=400, detail="Digest hat keinen Inhalt")

    try:
        pdf_bytes = await generate_pdf_from_html(digest.summary_html)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"PDF-Generierung fehlgeschlagen: {str(e)}")

    filename = f"wochenbericht_{digest.period_start.strftime('%Y%m%d')}_{digest.period_end.strftime('%Y%m%d')}.pdf"

    return StreamingResponse(
        io.BytesIO(pdf_bytes),
        media_type="application/pdf",
        headers={"Content-Disposition": f"attachment; filename={filename}"}
    )


@router.get("/latest/pdf")
async def get_latest_digest_pdf(db: DBSession = Depends(get_db)):
    """PDF des neuesten Digests herunterladen."""
    user_id = get_user_id_from_request()

    digest = db.query(AlertDigestDB).filter(
        AlertDigestDB.user_id == user_id
    ).order_by(AlertDigestDB.created_at.desc()).first()

    if not digest:
        raise HTTPException(status_code=404, detail="Kein Digest vorhanden")
    if not digest.summary_html:
        raise HTTPException(status_code=400, detail="Digest hat keinen Inhalt")

    try:
        pdf_bytes = await generate_pdf_from_html(digest.summary_html)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"PDF-Generierung fehlgeschlagen: {str(e)}")

    filename = f"wochenbericht_{digest.period_start.strftime('%Y%m%d')}_{digest.period_end.strftime('%Y%m%d')}.pdf"

    return StreamingResponse(
        io.BytesIO(pdf_bytes),
        media_type="application/pdf",
        headers={"Content-Disposition": f"attachment; filename={filename}"}
    )


@router.post("/generate", response_model=GenerateDigestResponse)
async def generate_digest(
    request: GenerateDigestRequest = None,
    db: DBSession = Depends(get_db)
):
    """Generiere einen neuen Digest manuell."""
    user_id = get_user_id_from_request()
    weeks_back = request.weeks_back if request else 1

    now = datetime.utcnow()
    period_end = now - timedelta(days=now.weekday())
    period_start = period_end - timedelta(weeks=weeks_back)

    existing = db.query(AlertDigestDB).filter(
        AlertDigestDB.user_id == user_id,
        AlertDigestDB.period_start >= period_start - timedelta(days=1),
        AlertDigestDB.period_end <= period_end + timedelta(days=1)
    ).first()

    if existing and not (request and request.force_regenerate):
        return GenerateDigestResponse(
            status="exists", digest_id=existing.id,
            message="Digest fuer diesen Zeitraum existiert bereits"
        )

    generator = DigestGenerator(db)

    try:
        digest = await generator.generate_weekly_digest(user_id, weeks_back)

        if digest:
            return GenerateDigestResponse(
                status="success", digest_id=digest.id,
                message="Digest erfolgreich generiert"
            )
        else:
            return GenerateDigestResponse(
                status="empty", digest_id=None,
                message="Keine Alerts fuer diesen Zeitraum vorhanden"
            )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Fehler bei Digest-Generierung: {str(e)}")


@router.post("/{digest_id}/send-email", response_model=SendEmailResponse)
async def send_digest_email(
    digest_id: str,
    request: SendEmailRequest = None,
    db: DBSession = Depends(get_db)
):
    """Versende Digest per E-Mail."""
    user_id = get_user_id_from_request()

    digest = db.query(AlertDigestDB).filter(
        AlertDigestDB.id == digest_id,
        AlertDigestDB.user_id == user_id
    ).first()

    if not digest:
        raise HTTPException(status_code=404, detail="Digest nicht gefunden")

    email = None
    if request and request.email:
        email = request.email
    else:
        subscription = db.query(UserAlertSubscriptionDB).filter(
            UserAlertSubscriptionDB.id == digest.subscription_id
        ).first()
        if subscription:
            email = subscription.notification_email

    if not email:
        raise HTTPException(status_code=400, detail="Keine E-Mail-Adresse angegeben")

    try:
        await send_digest_by_email(digest, email)

        digest.status = DigestStatusEnum.SENT
        digest.sent_at = datetime.utcnow()
        db.commit()

        return SendEmailResponse(
            status="success", sent_to=email,
            message="E-Mail erfolgreich versendet"
        )
    except Exception as e:
        digest.status = DigestStatusEnum.FAILED
        db.commit()
        raise HTTPException(status_code=500, detail=f"E-Mail-Versand fehlgeschlagen: {str(e)}")
