"""
Consent-Log Export (Borlabs-Parity + DSB-Audit-Anforderung).

Auditors verlangen routinemaessig einen Auszug aller erteilten/
widerrufenen Einwilligungen pro Tenant — heute musste der DSB dafuer
manuell SQL schreiben. Diese Endpunkte liefern CSV + JSON direkt aus
dem Browser.

Endpoints:
  GET  /einwilligungen/export/consents.csv
  GET  /einwilligungen/export/consents.json
  GET  /einwilligungen/export/history.csv  — Aenderungs-Historie
"""

from __future__ import annotations

import csv
import io
import json
import logging
from datetime import datetime, timezone

from fastapi import APIRouter, Depends, Header, Query
from fastapi.responses import Response
from sqlalchemy.orm import Session

from classroom_engine.database import get_db
from ..db.einwilligungen_models import (
    EinwilligungenConsentDB,
    EinwilligungenConsentHistoryDB,
)

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/einwilligungen/export", tags=["einwilligungen-export"])


def _get_tenant(x_tenant_id: str | None = Header(None, alias="X-Tenant-ID")) -> str:
    if not x_tenant_id:
        from .tenant_utils import get_tenant_id
        return get_tenant_id()
    return x_tenant_id


def _ts() -> str:
    return datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")


def _consent_rows(consents: list[EinwilligungenConsentDB]) -> list[dict]:
    return [
        {
            "consent_id": str(c.id),
            "user_id": c.user_id or "",
            "data_point_id": c.data_point_id or "",
            "granted": "yes" if c.granted else "no",
            "purpose": c.purpose or "",
            "consent_version": c.consent_version or "",
            "ip_address": c.ip_address or "",
            "user_agent": (c.user_agent or "")[:200],
            "source": c.source or "",
            "created_at": c.created_at.isoformat() if c.created_at else "",
            "updated_at": c.updated_at.isoformat() if c.updated_at else "",
            "revoked_at": c.revoked_at.isoformat() if getattr(c, "revoked_at", None) else "",
        }
        for c in consents
    ]


def _history_rows(entries: list[EinwilligungenConsentHistoryDB]) -> list[dict]:
    return [
        {
            "id": str(e.id),
            "consent_id": str(e.consent_id),
            "action": e.action or "",
            "consent_version": e.consent_version or "",
            "ip_address": e.ip_address or "",
            "user_agent": (e.user_agent or "")[:200],
            "source": e.source or "",
            "created_at": e.created_at.isoformat() if e.created_at else "",
        }
        for e in entries
    ]


def _csv_response(rows: list[dict], filename: str) -> Response:
    if not rows:
        return Response(content="", media_type="text/csv",
                        headers={"Content-Disposition": f"attachment; filename={filename}"})
    buf = io.StringIO()
    w = csv.DictWriter(buf, fieldnames=list(rows[0].keys()), quoting=csv.QUOTE_ALL)
    w.writeheader()
    w.writerows(rows)
    return Response(content=buf.getvalue(), media_type="text/csv; charset=utf-8",
                    headers={"Content-Disposition": f"attachment; filename={filename}"})


def _json_response(payload: dict, filename: str) -> Response:
    body = json.dumps(payload, ensure_ascii=False, indent=2, default=str)
    return Response(content=body, media_type="application/json; charset=utf-8",
                    headers={"Content-Disposition": f"attachment; filename={filename}"})


@router.get("/consents.csv")
async def export_consents_csv(
    user_id: str | None = Query(None, description="Filter by single user"),
    granted: bool | None = Query(None),
    since: str | None = Query(None, description="ISO timestamp"),
    tenant_id: str = Depends(_get_tenant),
    db: Session = Depends(get_db),
) -> Response:
    """Download all consent records of this tenant as CSV (auditor-ready)."""
    q = db.query(EinwilligungenConsentDB).filter(
        EinwilligungenConsentDB.tenant_id == tenant_id,
    )
    if user_id:
        q = q.filter(EinwilligungenConsentDB.user_id == user_id)
    if granted is not None:
        q = q.filter(EinwilligungenConsentDB.granted == granted)
    if since:
        try:
            since_dt = datetime.fromisoformat(since.rstrip("Z"))
            q = q.filter(EinwilligungenConsentDB.created_at >= since_dt)
        except Exception:
            pass
    rows = _consent_rows(q.order_by(EinwilligungenConsentDB.created_at.desc()).all())
    return _csv_response(rows, f"consents_{tenant_id[:8]}_{_ts()}.csv")


@router.get("/consents.json")
async def export_consents_json(
    user_id: str | None = Query(None),
    granted: bool | None = Query(None),
    since: str | None = Query(None),
    tenant_id: str = Depends(_get_tenant),
    db: Session = Depends(get_db),
) -> Response:
    """Same data as the CSV endpoint but JSON-shaped for further processing."""
    q = db.query(EinwilligungenConsentDB).filter(
        EinwilligungenConsentDB.tenant_id == tenant_id,
    )
    if user_id:
        q = q.filter(EinwilligungenConsentDB.user_id == user_id)
    if granted is not None:
        q = q.filter(EinwilligungenConsentDB.granted == granted)
    if since:
        try:
            since_dt = datetime.fromisoformat(since.rstrip("Z"))
            q = q.filter(EinwilligungenConsentDB.created_at >= since_dt)
        except Exception:
            pass
    rows = _consent_rows(q.order_by(EinwilligungenConsentDB.created_at.desc()).all())
    payload = {
        "tenant_id": tenant_id,
        "exported_at": datetime.now(timezone.utc).isoformat(),
        "filter": {"user_id": user_id, "granted": granted, "since": since},
        "count": len(rows),
        "consents": rows,
    }
    return _json_response(payload, f"consents_{tenant_id[:8]}_{_ts()}.json")


@router.get("/history.csv")
async def export_history_csv(
    consent_id: str | None = Query(None, description="Limit to one consent"),
    since: str | None = Query(None),
    tenant_id: str = Depends(_get_tenant),
    db: Session = Depends(get_db),
) -> Response:
    """Download the consent-change history (Art. 7(1) Nachweispflicht)."""
    q = db.query(EinwilligungenConsentHistoryDB).filter(
        EinwilligungenConsentHistoryDB.tenant_id == tenant_id,
    )
    if consent_id:
        q = q.filter(EinwilligungenConsentHistoryDB.consent_id == consent_id)
    if since:
        try:
            since_dt = datetime.fromisoformat(since.rstrip("Z"))
            q = q.filter(EinwilligungenConsentHistoryDB.created_at >= since_dt)
        except Exception:
            pass
    rows = _history_rows(q.order_by(EinwilligungenConsentHistoryDB.created_at.asc()).all())
    return _csv_response(rows, f"consent-history_{tenant_id[:8]}_{_ts()}.csv")
