"""
FastAPI routes for Consent Email Templates + DSGVO Processes.

Endpoints:
  GET    /consent-templates              — List email templates (filtered by tenant)
  POST   /consent-templates             — Create a new email template
  PUT    /consent-templates/{id}        — Update an email template
  DELETE /consent-templates/{id}        — Delete an email template
  GET    /gdpr-processes                — List GDPR processes
  PUT    /gdpr-processes/{id}           — Update a GDPR process
"""

import logging
from datetime import datetime, timezone
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Header
from pydantic import BaseModel
from sqlalchemy.orm import Session
from sqlalchemy import text

from classroom_engine.database import get_db

logger = logging.getLogger(__name__)
router = APIRouter(tags=["consent-templates"])


# ============================================================================
# Pydantic Schemas
# ============================================================================

class ConsentTemplateCreate(BaseModel):
    template_key: str
    subject: str
    body: str
    language: str = 'de'
    is_active: bool = True


class ConsentTemplateUpdate(BaseModel):
    subject: Optional[str] = None
    body: Optional[str] = None
    is_active: Optional[bool] = None


class GDPRProcessUpdate(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    legal_basis: Optional[str] = None
    retention_days: Optional[int] = None
    is_active: Optional[bool] = None


# ============================================================================
# Helpers
# ============================================================================

def _get_tenant(x_tenant_id: Optional[str] = Header(None, alias='X-Tenant-ID')) -> str:
    return x_tenant_id or 'default'


# ============================================================================
# Email Templates
# ============================================================================

@router.get("/consent-templates")
async def list_consent_templates(
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant),
):
    """List all email templates for a tenant."""
    rows = db.execute(
        text("""
            SELECT id, tenant_id, template_key, subject, body, language, is_active, created_at, updated_at
            FROM compliance_consent_email_templates
            WHERE tenant_id = :tenant_id
            ORDER BY template_key, language
        """),
        {"tenant_id": tenant_id},
    ).fetchall()

    return [
        {
            "id": str(r.id),
            "tenant_id": r.tenant_id,
            "template_key": r.template_key,
            "subject": r.subject,
            "body": r.body,
            "language": r.language,
            "is_active": r.is_active,
            "created_at": r.created_at.isoformat() if r.created_at else None,
            "updated_at": r.updated_at.isoformat() if r.updated_at else None,
        }
        for r in rows
    ]


@router.post("/consent-templates", status_code=201)
async def create_consent_template(
    request: ConsentTemplateCreate,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant),
):
    """Create a new email template."""
    existing = db.execute(
        text("""
            SELECT id FROM compliance_consent_email_templates
            WHERE tenant_id = :tenant_id AND template_key = :template_key AND language = :language
        """),
        {"tenant_id": tenant_id, "template_key": request.template_key, "language": request.language},
    ).fetchone()

    if existing:
        raise HTTPException(
            status_code=409,
            detail=f"Template '{request.template_key}' for language '{request.language}' already exists for this tenant",
        )

    row = db.execute(
        text("""
            INSERT INTO compliance_consent_email_templates
                (tenant_id, template_key, subject, body, language, is_active)
            VALUES (:tenant_id, :template_key, :subject, :body, :language, :is_active)
            RETURNING id, tenant_id, template_key, subject, body, language, is_active, created_at, updated_at
        """),
        {
            "tenant_id": tenant_id,
            "template_key": request.template_key,
            "subject": request.subject,
            "body": request.body,
            "language": request.language,
            "is_active": request.is_active,
        },
    ).fetchone()
    db.commit()

    return {
        "id": str(row.id),
        "tenant_id": row.tenant_id,
        "template_key": row.template_key,
        "subject": row.subject,
        "body": row.body,
        "language": row.language,
        "is_active": row.is_active,
        "created_at": row.created_at.isoformat() if row.created_at else None,
        "updated_at": row.updated_at.isoformat() if row.updated_at else None,
    }


@router.put("/consent-templates/{template_id}")
async def update_consent_template(
    template_id: str,
    request: ConsentTemplateUpdate,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant),
):
    """Update an existing email template."""
    existing = db.execute(
        text("""
            SELECT id FROM compliance_consent_email_templates
            WHERE id = :id AND tenant_id = :tenant_id
        """),
        {"id": template_id, "tenant_id": tenant_id},
    ).fetchone()

    if not existing:
        raise HTTPException(status_code=404, detail=f"Template {template_id} not found")

    updates = request.dict(exclude_none=True)
    if not updates:
        raise HTTPException(status_code=400, detail="No fields to update")

    set_clauses = ", ".join(f"{k} = :{k}" for k in updates)
    updates["id"] = template_id
    updates["tenant_id"] = tenant_id
    updates["now"] = datetime.now(timezone.utc)

    row = db.execute(
        text(f"""
            UPDATE compliance_consent_email_templates
            SET {set_clauses}, updated_at = :now
            WHERE id = :id AND tenant_id = :tenant_id
            RETURNING id, tenant_id, template_key, subject, body, language, is_active, created_at, updated_at
        """),
        updates,
    ).fetchone()
    db.commit()

    return {
        "id": str(row.id),
        "tenant_id": row.tenant_id,
        "template_key": row.template_key,
        "subject": row.subject,
        "body": row.body,
        "language": row.language,
        "is_active": row.is_active,
        "created_at": row.created_at.isoformat() if row.created_at else None,
        "updated_at": row.updated_at.isoformat() if row.updated_at else None,
    }


@router.delete("/consent-templates/{template_id}")
async def delete_consent_template(
    template_id: str,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant),
):
    """Delete an email template."""
    existing = db.execute(
        text("""
            SELECT id FROM compliance_consent_email_templates
            WHERE id = :id AND tenant_id = :tenant_id
        """),
        {"id": template_id, "tenant_id": tenant_id},
    ).fetchone()

    if not existing:
        raise HTTPException(status_code=404, detail=f"Template {template_id} not found")

    db.execute(
        text("DELETE FROM compliance_consent_email_templates WHERE id = :id AND tenant_id = :tenant_id"),
        {"id": template_id, "tenant_id": tenant_id},
    )
    db.commit()

    return {"success": True, "message": f"Template {template_id} deleted"}


# ============================================================================
# GDPR Processes
# ============================================================================

@router.get("/gdpr-processes")
async def list_gdpr_processes(
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant),
):
    """List all GDPR processes for a tenant."""
    rows = db.execute(
        text("""
            SELECT id, tenant_id, process_key, title, description, legal_basis, retention_days, is_active, created_at
            FROM compliance_consent_gdpr_processes
            WHERE tenant_id = :tenant_id
            ORDER BY process_key
        """),
        {"tenant_id": tenant_id},
    ).fetchall()

    return [
        {
            "id": str(r.id),
            "tenant_id": r.tenant_id,
            "process_key": r.process_key,
            "title": r.title,
            "description": r.description,
            "legal_basis": r.legal_basis,
            "retention_days": r.retention_days,
            "is_active": r.is_active,
            "created_at": r.created_at.isoformat() if r.created_at else None,
        }
        for r in rows
    ]


@router.put("/gdpr-processes/{process_id}")
async def update_gdpr_process(
    process_id: str,
    request: GDPRProcessUpdate,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant),
):
    """Update an existing GDPR process."""
    existing = db.execute(
        text("""
            SELECT id FROM compliance_consent_gdpr_processes
            WHERE id = :id AND tenant_id = :tenant_id
        """),
        {"id": process_id, "tenant_id": tenant_id},
    ).fetchone()

    if not existing:
        raise HTTPException(status_code=404, detail=f"GDPR process {process_id} not found")

    updates = request.dict(exclude_none=True)
    if not updates:
        raise HTTPException(status_code=400, detail="No fields to update")

    set_clauses = ", ".join(f"{k} = :{k}" for k in updates)
    updates["id"] = process_id
    updates["tenant_id"] = tenant_id

    row = db.execute(
        text(f"""
            UPDATE compliance_consent_gdpr_processes
            SET {set_clauses}
            WHERE id = :id AND tenant_id = :tenant_id
            RETURNING id, tenant_id, process_key, title, description, legal_basis, retention_days, is_active, created_at
        """),
        updates,
    ).fetchone()
    db.commit()

    return {
        "id": str(row.id),
        "tenant_id": row.tenant_id,
        "process_key": row.process_key,
        "title": row.title,
        "description": row.description,
        "legal_basis": row.legal_basis,
        "retention_days": row.retention_days,
        "is_active": row.is_active,
        "created_at": row.created_at.isoformat() if row.created_at else None,
    }
