"""
FastAPI routes for Compliance Process Manager — recurring compliance tasks.

Endpoints:
  GET    /process-tasks              — list with filters (status, category, frequency, overdue, etc.)
  GET    /process-tasks/stats        — counts by status, category, due windows
  GET    /process-tasks/upcoming     — tasks due in next N days
  POST   /process-tasks              — create task
  GET    /process-tasks/{id}         — single task
  PUT    /process-tasks/{id}         — update task
  DELETE /process-tasks/{id}         — delete task
  POST   /process-tasks/{id}/complete — complete a task (with history + next_due recalc)
  POST   /process-tasks/{id}/skip    — skip a task (with reason + next_due recalc)
  GET    /process-tasks/{id}/history  — task history entries
  POST   /process-tasks/seed         — seed ~50 standard tasks (idempotent)
"""

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

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

from classroom_engine.database import get_db
from .tenant_utils import get_tenant_id as _get_tenant_id
from .db_utils import row_to_dict as _row_to_dict

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

# =============================================================================
# Constants
# =============================================================================

VALID_CATEGORIES = {"dsgvo", "nis2", "bsi", "iso27001", "ai_act", "internal"}
VALID_PRIORITIES = {"critical", "high", "medium", "low"}
VALID_FREQUENCIES = {"weekly", "monthly", "quarterly", "semi_annual", "yearly", "once"}
VALID_STATUSES = {"pending", "in_progress", "completed", "overdue", "skipped"}

FREQUENCY_DAYS = {
    "weekly": 7,
    "monthly": 30,
    "quarterly": 90,
    "semi_annual": 182,
    "yearly": 365,
    "once": None,
}

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


class ProcessTaskCreate(BaseModel):
    task_code: str
    title: str
    description: Optional[str] = None
    category: str
    priority: str = "medium"
    frequency: str = "yearly"
    assigned_to: Optional[str] = None
    responsible_team: Optional[str] = None
    linked_control_ids: Optional[List] = []
    linked_module: Optional[str] = None
    next_due_date: Optional[str] = None
    due_reminder_days: int = 14
    notes: Optional[str] = None
    tags: Optional[List] = []


class ProcessTaskUpdate(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    category: Optional[str] = None
    priority: Optional[str] = None
    frequency: Optional[str] = None
    assigned_to: Optional[str] = None
    responsible_team: Optional[str] = None
    linked_control_ids: Optional[List] = None
    linked_module: Optional[str] = None
    next_due_date: Optional[str] = None
    due_reminder_days: Optional[int] = None
    status: Optional[str] = None
    notes: Optional[str] = None
    tags: Optional[List] = None


class ProcessTaskComplete(BaseModel):
    completed_by: Optional[str] = None
    result: Optional[str] = None
    evidence_id: Optional[str] = None
    notes: Optional[str] = None


class ProcessTaskSkip(BaseModel):
    reason: str


# =============================================================================
# Routes
# =============================================================================


@router.get("")
async def list_tasks(
    status: Optional[str] = Query(None),
    category: Optional[str] = Query(None),
    frequency: Optional[str] = Query(None),
    assigned_to: Optional[str] = Query(None),
    overdue: Optional[bool] = Query(None),
    limit: int = Query(100, ge=1, le=500),
    offset: int = Query(0, ge=0),
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
):
    """List process tasks with optional filters."""

    where_clauses = ["tenant_id = :tenant_id"]
    params: Dict[str, Any] = {"tenant_id": tenant_id, "limit": limit, "offset": offset}

    if status:
        where_clauses.append("status = :status")
        params["status"] = status
    if category:
        where_clauses.append("category = :category")
        params["category"] = category
    if frequency:
        where_clauses.append("frequency = :frequency")
        params["frequency"] = frequency
    if assigned_to:
        where_clauses.append("assigned_to ILIKE :assigned_to")
        params["assigned_to"] = f"%{assigned_to}%"
    if overdue:
        where_clauses.append("next_due_date < CURRENT_DATE AND status NOT IN ('completed','skipped')")

    where_sql = " AND ".join(where_clauses)

    total_row = db.execute(
        text(f"SELECT COUNT(*) FROM compliance_process_tasks WHERE {where_sql}"),
        params,
    ).fetchone()
    total = total_row[0] if total_row else 0

    rows = db.execute(
        text(f"""
            SELECT * FROM compliance_process_tasks
            WHERE {where_sql}
            ORDER BY
                CASE priority
                    WHEN 'critical' THEN 0
                    WHEN 'high' THEN 1
                    WHEN 'medium' THEN 2
                    ELSE 3
                END,
                next_due_date ASC NULLS LAST,
                created_at DESC
            LIMIT :limit OFFSET :offset
        """),
        params,
    ).fetchall()

    return {
        "tasks": [_row_to_dict(r) for r in rows],
        "total": total,
    }


@router.get("/stats")
async def get_stats(
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
):
    """Return task counts by status, category, and due windows."""

    row = db.execute(text("""
        SELECT
            COUNT(*)                                                         AS total,
            COUNT(*) FILTER (WHERE status = 'pending')                       AS pending,
            COUNT(*) FILTER (WHERE status = 'in_progress')                   AS in_progress,
            COUNT(*) FILTER (WHERE status = 'completed')                     AS completed,
            COUNT(*) FILTER (WHERE status = 'overdue')                       AS overdue,
            COUNT(*) FILTER (WHERE status = 'skipped')                       AS skipped,
            COUNT(*) FILTER (WHERE next_due_date < CURRENT_DATE
                             AND status NOT IN ('completed','skipped'))       AS overdue_count,
            COUNT(*) FILTER (WHERE next_due_date <= CURRENT_DATE + 7
                             AND next_due_date >= CURRENT_DATE
                             AND status NOT IN ('completed','skipped'))       AS due_7_days,
            COUNT(*) FILTER (WHERE next_due_date <= CURRENT_DATE + 14
                             AND next_due_date >= CURRENT_DATE
                             AND status NOT IN ('completed','skipped'))       AS due_14_days,
            COUNT(*) FILTER (WHERE next_due_date <= CURRENT_DATE + 30
                             AND next_due_date >= CURRENT_DATE
                             AND status NOT IN ('completed','skipped'))       AS due_30_days
        FROM compliance_process_tasks
        WHERE tenant_id = :tenant_id
    """), {"tenant_id": tenant_id}).fetchone()

    by_status = {}
    by_category = {}
    if row:
        d = dict(row._mapping)
        by_status = {
            "pending": d.get("pending", 0) or 0,
            "in_progress": d.get("in_progress", 0) or 0,
            "completed": d.get("completed", 0) or 0,
            "overdue": d.get("overdue", 0) or 0,
            "skipped": d.get("skipped", 0) or 0,
        }
    else:
        d = {}

    # Category counts
    cat_rows = db.execute(text("""
        SELECT category, COUNT(*) AS cnt
        FROM compliance_process_tasks
        WHERE tenant_id = :tenant_id
        GROUP BY category
    """), {"tenant_id": tenant_id}).fetchall()
    by_category = {r._mapping["category"]: r._mapping["cnt"] for r in cat_rows}

    return {
        "total": (d.get("total", 0) or 0),
        "by_status": by_status,
        "by_category": by_category,
        "overdue_count": (d.get("overdue_count", 0) or 0),
        "due_7_days": (d.get("due_7_days", 0) or 0),
        "due_14_days": (d.get("due_14_days", 0) or 0),
        "due_30_days": (d.get("due_30_days", 0) or 0),
    }


@router.get("/upcoming")
async def get_upcoming(
    days: int = Query(30, ge=1, le=365),
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
):
    """Tasks due in next N days."""

    rows = db.execute(text("""
        SELECT * FROM compliance_process_tasks
        WHERE tenant_id = :tenant_id
          AND next_due_date IS NOT NULL
          AND next_due_date <= CURRENT_DATE + :days
          AND next_due_date >= CURRENT_DATE
          AND status NOT IN ('completed','skipped')
        ORDER BY next_due_date ASC
    """), {"tenant_id": tenant_id, "days": days}).fetchall()

    return {"tasks": [_row_to_dict(r) for r in rows]}


@router.post("", status_code=201)
async def create_task(
    payload: ProcessTaskCreate,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
    x_user_id: Optional[str] = Header(None),
):
    """Create a new process task."""
    logger.info("create_task user_id=%s tenant_id=%s code=%s", x_user_id, tenant_id, payload.task_code)

    if payload.category not in VALID_CATEGORIES:
        raise HTTPException(status_code=400, detail=f"Invalid category. Must be one of: {', '.join(sorted(VALID_CATEGORIES))}")
    if payload.priority not in VALID_PRIORITIES:
        raise HTTPException(status_code=400, detail=f"Invalid priority. Must be one of: {', '.join(sorted(VALID_PRIORITIES))}")
    if payload.frequency not in VALID_FREQUENCIES:
        raise HTTPException(status_code=400, detail=f"Invalid frequency. Must be one of: {', '.join(sorted(VALID_FREQUENCIES))}")

    row = db.execute(text("""
        INSERT INTO compliance_process_tasks
            (tenant_id, task_code, title, description, category, priority, frequency,
             assigned_to, responsible_team, linked_control_ids, linked_module,
             next_due_date, due_reminder_days, notes, tags)
        VALUES
            (:tenant_id, :task_code, :title, :description, :category, :priority, :frequency,
             :assigned_to, :responsible_team, CAST(:linked_control_ids AS jsonb), :linked_module,
             :next_due_date, :due_reminder_days, :notes, CAST(:tags AS jsonb))
        RETURNING *
    """), {
        "tenant_id": tenant_id,
        "task_code": payload.task_code,
        "title": payload.title,
        "description": payload.description,
        "category": payload.category,
        "priority": payload.priority,
        "frequency": payload.frequency,
        "assigned_to": payload.assigned_to,
        "responsible_team": payload.responsible_team,
        "linked_control_ids": json.dumps(payload.linked_control_ids or []),
        "linked_module": payload.linked_module,
        "next_due_date": payload.next_due_date,
        "due_reminder_days": payload.due_reminder_days,
        "notes": payload.notes,
        "tags": json.dumps(payload.tags or []),
    }).fetchone()
    db.commit()
    return _row_to_dict(row)


@router.get("/{task_id}")
async def get_task(
    task_id: str,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
):
    """Get single process task."""
    row = db.execute(text("""
        SELECT * FROM compliance_process_tasks
        WHERE id = :id AND tenant_id = :tenant_id
    """), {"id": task_id, "tenant_id": tenant_id}).fetchone()
    if not row:
        raise HTTPException(status_code=404, detail="Task not found")
    return _row_to_dict(row)


@router.put("/{task_id}")
async def update_task(
    task_id: str,
    payload: ProcessTaskUpdate,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
    x_user_id: Optional[str] = Header(None),
):
    """Update a process task."""
    logger.info("update_task user_id=%s tenant_id=%s id=%s", x_user_id, tenant_id, task_id)

    updates: Dict[str, Any] = {"id": task_id, "tenant_id": tenant_id, "updated_at": datetime.utcnow()}
    set_clauses = ["updated_at = :updated_at"]

    data = payload.model_dump(exclude_unset=True)

    # Validate enum fields if provided
    if "category" in data and data["category"] not in VALID_CATEGORIES:
        raise HTTPException(status_code=400, detail=f"Invalid category. Must be one of: {', '.join(sorted(VALID_CATEGORIES))}")
    if "priority" in data and data["priority"] not in VALID_PRIORITIES:
        raise HTTPException(status_code=400, detail=f"Invalid priority. Must be one of: {', '.join(sorted(VALID_PRIORITIES))}")
    if "frequency" in data and data["frequency"] not in VALID_FREQUENCIES:
        raise HTTPException(status_code=400, detail=f"Invalid frequency. Must be one of: {', '.join(sorted(VALID_FREQUENCIES))}")
    if "status" in data and data["status"] not in VALID_STATUSES:
        raise HTTPException(status_code=400, detail=f"Invalid status. Must be one of: {', '.join(sorted(VALID_STATUSES))}")

    for field, value in data.items():
        if field in ("linked_control_ids", "tags", "follow_up_actions"):
            updates[field] = json.dumps(value or [])
            set_clauses.append(f"{field} = CAST(:{field} AS jsonb)")
        else:
            updates[field] = value
            set_clauses.append(f"{field} = :{field}")

    if len(set_clauses) == 1:
        raise HTTPException(status_code=400, detail="No fields to update")

    row = db.execute(text(f"""
        UPDATE compliance_process_tasks
        SET {', '.join(set_clauses)}
        WHERE id = :id AND tenant_id = :tenant_id
        RETURNING *
    """), updates).fetchone()
    db.commit()

    if not row:
        raise HTTPException(status_code=404, detail="Task not found")
    return _row_to_dict(row)


@router.delete("/{task_id}", status_code=204)
async def delete_task(
    task_id: str,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
    x_user_id: Optional[str] = Header(None),
):
    """Delete a process task."""
    logger.info("delete_task user_id=%s tenant_id=%s id=%s", x_user_id, tenant_id, task_id)
    result = db.execute(text("""
        DELETE FROM compliance_process_tasks
        WHERE id = :id AND tenant_id = :tenant_id
    """), {"id": task_id, "tenant_id": tenant_id})
    db.commit()
    if result.rowcount == 0:
        raise HTTPException(status_code=404, detail="Task not found")


@router.post("/{task_id}/complete")
async def complete_task(
    task_id: str,
    payload: ProcessTaskComplete,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
    x_user_id: Optional[str] = Header(None),
):
    """Complete a task: insert history, update task, calculate next due date."""
    logger.info("complete_task user_id=%s tenant_id=%s id=%s", x_user_id, tenant_id, task_id)

    # Fetch current task
    task_row = db.execute(text("""
        SELECT * FROM compliance_process_tasks
        WHERE id = :id AND tenant_id = :tenant_id
    """), {"id": task_id, "tenant_id": tenant_id}).fetchone()

    if not task_row:
        raise HTTPException(status_code=404, detail="Task not found")

    task = dict(task_row._mapping)

    # Insert history entry
    db.execute(text("""
        INSERT INTO compliance_process_task_history
            (task_id, completed_by, completed_at, result, evidence_id, notes, status)
        VALUES
            (:task_id, :completed_by, NOW(), :result, :evidence_id, :notes, 'completed')
    """), {
        "task_id": task_id,
        "completed_by": payload.completed_by,
        "result": payload.result,
        "evidence_id": payload.evidence_id,
        "notes": payload.notes,
    })

    # Calculate next due date
    freq = task.get("frequency", "yearly")
    days_delta = FREQUENCY_DAYS.get(freq)

    if days_delta is not None:
        # Recurring task — set next due and reset to pending
        row = db.execute(text("""
            UPDATE compliance_process_tasks
            SET last_completed_at = NOW(),
                status = 'pending',
                completion_date = NOW(),
                completion_result = :result,
                completion_evidence_id = :evidence_id,
                next_due_date = CURRENT_DATE + :days_delta,
                updated_at = NOW()
            WHERE id = :id AND tenant_id = :tenant_id
            RETURNING *
        """), {
            "id": task_id,
            "tenant_id": tenant_id,
            "result": payload.result,
            "evidence_id": payload.evidence_id,
            "days_delta": days_delta,
        }).fetchone()
    else:
        # One-time task — mark completed, no next due
        row = db.execute(text("""
            UPDATE compliance_process_tasks
            SET last_completed_at = NOW(),
                status = 'completed',
                completion_date = NOW(),
                completion_result = :result,
                completion_evidence_id = :evidence_id,
                next_due_date = NULL,
                updated_at = NOW()
            WHERE id = :id AND tenant_id = :tenant_id
            RETURNING *
        """), {
            "id": task_id,
            "tenant_id": tenant_id,
            "result": payload.result,
            "evidence_id": payload.evidence_id,
        }).fetchone()

    db.commit()
    return _row_to_dict(row)


@router.post("/{task_id}/skip")
async def skip_task(
    task_id: str,
    payload: ProcessTaskSkip,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
    x_user_id: Optional[str] = Header(None),
):
    """Skip a task with reason: insert history, calculate next due date."""
    logger.info("skip_task user_id=%s tenant_id=%s id=%s", x_user_id, tenant_id, task_id)

    # Fetch current task
    task_row = db.execute(text("""
        SELECT * FROM compliance_process_tasks
        WHERE id = :id AND tenant_id = :tenant_id
    """), {"id": task_id, "tenant_id": tenant_id}).fetchone()

    if not task_row:
        raise HTTPException(status_code=404, detail="Task not found")

    task = dict(task_row._mapping)

    # Insert history entry
    db.execute(text("""
        INSERT INTO compliance_process_task_history
            (task_id, completed_by, completed_at, result, notes, status)
        VALUES
            (:task_id, :completed_by, NOW(), :reason, :reason, 'skipped')
    """), {
        "task_id": task_id,
        "completed_by": x_user_id,
        "reason": payload.reason,
    })

    # Calculate next due date
    freq = task.get("frequency", "yearly")
    days_delta = FREQUENCY_DAYS.get(freq)

    if days_delta is not None:
        row = db.execute(text("""
            UPDATE compliance_process_tasks
            SET status = 'pending',
                next_due_date = CURRENT_DATE + :days_delta,
                updated_at = NOW()
            WHERE id = :id AND tenant_id = :tenant_id
            RETURNING *
        """), {
            "id": task_id,
            "tenant_id": tenant_id,
            "days_delta": days_delta,
        }).fetchone()
    else:
        row = db.execute(text("""
            UPDATE compliance_process_tasks
            SET status = 'skipped',
                next_due_date = NULL,
                updated_at = NOW()
            WHERE id = :id AND tenant_id = :tenant_id
            RETURNING *
        """), {
            "id": task_id,
            "tenant_id": tenant_id,
        }).fetchone()

    db.commit()
    return _row_to_dict(row)


@router.get("/{task_id}/history")
async def get_task_history(
    task_id: str,
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
):
    """Return history entries for a task."""
    # Verify task belongs to tenant
    task_row = db.execute(text("""
        SELECT id FROM compliance_process_tasks
        WHERE id = :id AND tenant_id = :tenant_id
    """), {"id": task_id, "tenant_id": tenant_id}).fetchone()

    if not task_row:
        raise HTTPException(status_code=404, detail="Task not found")

    rows = db.execute(text("""
        SELECT * FROM compliance_process_task_history
        WHERE task_id = :task_id
        ORDER BY completed_at DESC
    """), {"task_id": task_id}).fetchall()

    return {"history": [_row_to_dict(r) for r in rows]}


@router.post("/seed")
async def seed_tasks(
    db: Session = Depends(get_db),
    tenant_id: str = Depends(_get_tenant_id),
    x_user_id: Optional[str] = Header(None),
):
    """Seed ~50 standard compliance tasks. Idempotent via ON CONFLICT."""
    logger.info("seed_tasks user_id=%s tenant_id=%s", x_user_id, tenant_id)

    seeds = _get_seed_tasks()
    inserted = 0

    for s in seeds:
        result = db.execute(text("""
            INSERT INTO compliance_process_tasks
                (tenant_id, task_code, title, description, category, priority, frequency,
                 linked_module, is_seed, next_due_date)
            VALUES
                (:tenant_id, :task_code, :title, :description, :category, :priority, :frequency,
                 :linked_module, TRUE, CURRENT_DATE + :initial_days)
            ON CONFLICT (tenant_id, project_id, task_code) DO NOTHING
        """), {
            "tenant_id": tenant_id,
            "task_code": s["task_code"],
            "title": s["title"],
            "description": s["description"],
            "category": s["category"],
            "priority": s["priority"],
            "frequency": s["frequency"],
            "linked_module": s.get("linked_module"),
            "initial_days": FREQUENCY_DAYS.get(s["frequency"], 365) or 365,
        })
        if result.rowcount > 0:
            inserted += 1

    db.commit()

    return {"seeded": inserted, "total_available": len(seeds)}


# =============================================================================
# Seed Data
# =============================================================================

def _get_seed_tasks() -> List[Dict[str, Any]]:
    """Return ~50 standard compliance tasks for seeding."""
    return [
        # ─── DSGVO (~15) ─────────────────────────────────────────────
        {
            "task_code": "DSGVO-VVT-REVIEW",
            "title": "VVT-Review und Aktualisierung",
            "description": "Jaehrliche Ueberpruefung und Aktualisierung des Verzeichnisses von Verarbeitungstaetigkeiten gemaess Art. 30 DSGVO.",
            "category": "dsgvo",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": "vvt",
        },
        {
            "task_code": "DSGVO-TOM-REVIEW",
            "title": "TOM-Review und Aktualisierung",
            "description": "Jaehrliche Ueberpruefung der technischen und organisatorischen Massnahmen gemaess Art. 32 DSGVO.",
            "category": "dsgvo",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": "tom",
        },
        {
            "task_code": "DSGVO-LOESCHFRISTEN",
            "title": "Loeschfristen-Pruefung",
            "description": "Quartalspruefung aller Loeschfristen und Durchfuehrung faelliger Loeschungen.",
            "category": "dsgvo",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": "loeschfristen",
        },
        {
            "task_code": "DSGVO-DSB-BERICHT",
            "title": "DSB-Taetigkeitsbericht",
            "description": "Jaehrlicher Taetigkeitsbericht des Datenschutzbeauftragten an die Geschaeftsfuehrung.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "DSGVO-DSFA-UPDATE",
            "title": "DSFA-Aktualisierung",
            "description": "Jaehrliche Ueberpruefung und Aktualisierung der Datenschutz-Folgenabschaetzungen.",
            "category": "dsgvo",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": "dsfa",
        },
        {
            "task_code": "DSGVO-SCHULUNG",
            "title": "Datenschutz-Schulung Mitarbeiter",
            "description": "Jaehrliche Datenschutz-Schulung fuer alle Mitarbeiter mit Nachweis.",
            "category": "dsgvo",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": "training",
        },
        {
            "task_code": "DSGVO-BETROFFENENRECHTE",
            "title": "Betroffenenrechte-Prozess testen",
            "description": "Quartalstest der Prozesse fuer Auskunft, Berichtigung, Loeschung und Datenportabilitaet.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "quarterly",
            "linked_module": "dsr",
        },
        {
            "task_code": "DSGVO-AV-VERTRAEGE",
            "title": "AV-Vertraege pruefen",
            "description": "Jaehrliche Pruefung aller Auftragsverarbeitungsvertraege auf Aktualitaet und Vollstaendigkeit.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": "vendor-compliance",
        },
        {
            "task_code": "DSGVO-DATENPANNE-TEST",
            "title": "Datenpannen-Meldeprozess testen",
            "description": "Halbjahrestest des Meldeprozesses fuer Datenschutzverletzungen gemaess Art. 33/34 DSGVO.",
            "category": "dsgvo",
            "priority": "high",
            "frequency": "semi_annual",
            "linked_module": "incident-response",
        },
        {
            "task_code": "DSGVO-COOKIE-PRUEFUNG",
            "title": "Cookie-Banner und Consent pruefen",
            "description": "Quartalspruefung des Cookie-Banners und der Einwilligungsmechanismen.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "quarterly",
            "linked_module": "consent",
        },
        {
            "task_code": "DSGVO-DSE-REVIEW",
            "title": "Datenschutzerklaerung Review",
            "description": "Halbjaehrliche Ueberpruefung der Datenschutzerklaerung auf Aktualitaet.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "semi_annual",
            "linked_module": "document-generator",
        },
        {
            "task_code": "DSGVO-EINWILLIGUNG-REVIEW",
            "title": "Einwilligungen Review",
            "description": "Quartalspruefung der eingeholten Einwilligungen auf Gueltigkeit und Widerrufbarkeit.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "quarterly",
            "linked_module": "consent",
        },
        {
            "task_code": "DSGVO-DRITTLAND",
            "title": "Drittlandsuebermittlung pruefen",
            "description": "Jaehrliche Pruefung aller Datenuebermittlungen in Drittlaender und deren Rechtsgrundlage.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "DSGVO-VERPFLICHTUNG",
            "title": "Mitarbeiter-Verpflichtung Datengeheimnis",
            "description": "Jaehrliche Pruefung, ob alle Mitarbeiter auf das Datengeheimnis verpflichtet wurden.",
            "category": "dsgvo",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "DSGVO-DATENKATEGORIEN",
            "title": "Datenkategorien-Review",
            "description": "Jaehrliche Ueberpruefung der erfassten Datenkategorien und deren Zuordnung.",
            "category": "dsgvo",
            "priority": "low",
            "frequency": "yearly",
            "linked_module": "vvt",
        },

        # ─── NIS2 (~10) ──────────────────────────────────────────────
        {
            "task_code": "NIS2-RISIKOBEWERTUNG",
            "title": "NIS2 Risikobewertung",
            "description": "Jaehrliche umfassende Risikobewertung der Netz- und Informationssicherheit.",
            "category": "nis2",
            "priority": "critical",
            "frequency": "yearly",
            "linked_module": "risks",
        },
        {
            "task_code": "NIS2-LIEFERKETTE",
            "title": "Lieferketten-Sicherheitspruefung",
            "description": "Jaehrliche Ueberpruefung der Sicherheitsmassnahmen bei Zulieferern und Dienstleistern.",
            "category": "nis2",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": "vendor-compliance",
        },
        {
            "task_code": "NIS2-INCIDENT-UEBUNG",
            "title": "Incident-Response-Uebung",
            "description": "Jaehrliche Uebung des Incident-Response-Prozesses mit Dokumentation.",
            "category": "nis2",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": "incident-response",
        },
        {
            "task_code": "NIS2-VULNSCAN",
            "title": "Vulnerability-Scan",
            "description": "Monatlicher automatisierter Vulnerability-Scan aller IT-Systeme.",
            "category": "nis2",
            "priority": "critical",
            "frequency": "monthly",
            "linked_module": "security-backlog",
        },
        {
            "task_code": "NIS2-PATCHMGMT",
            "title": "Patch-Management-Review",
            "description": "Monatliche Pruefung des Patch-Status aller Systeme.",
            "category": "nis2",
            "priority": "high",
            "frequency": "monthly",
            "linked_module": "security-backlog",
        },
        {
            "task_code": "NIS2-BCM-TEST",
            "title": "Business-Continuity-Test",
            "description": "Jaehrlicher Test des Business-Continuity-Plans.",
            "category": "nis2",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "NIS2-ZUGANGSKONTROLLE",
            "title": "Zugangskontrollen-Review",
            "description": "Quartalspruefung aller Zugangsberechtigungen und Accounts.",
            "category": "nis2",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "NIS2-KRYPTOGRAFIE",
            "title": "Kryptografie-Review",
            "description": "Jaehrliche Ueberpruefung der eingesetzten kryptografischen Verfahren.",
            "category": "nis2",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "NIS2-MELDEPFLICHT",
            "title": "Meldepflicht-Prozess testen",
            "description": "Halbjaehrlicher Test des NIS2-Meldeprozesses (24h/72h Fristen).",
            "category": "nis2",
            "priority": "high",
            "frequency": "semi_annual",
            "linked_module": None,
        },
        {
            "task_code": "NIS2-NETZSEGMENT",
            "title": "Netzwerksegmentierung-Review",
            "description": "Jaehrliche Ueberpruefung der Netzwerksegmentierung und Firewall-Regeln.",
            "category": "nis2",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": None,
        },

        # ─── BSI (~10) ───────────────────────────────────────────────
        {
            "task_code": "BSI-GRUNDSCHUTZ",
            "title": "IT-Grundschutz-Check",
            "description": "Jaehrlicher IT-Grundschutz-Check nach BSI-Standard 200-2.",
            "category": "bsi",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-BAUSTEIN",
            "title": "Baustein-Review",
            "description": "Quartalspruefung der implementierten BSI-Bausteine.",
            "category": "bsi",
            "priority": "medium",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-NOTFALLPLAN",
            "title": "Notfallplan-Test",
            "description": "Jaehrlicher Test des IT-Notfallplans mit Uebungsszenario.",
            "category": "bsi",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": "notfallplan",
        },
        {
            "task_code": "BSI-BACKUP-TEST",
            "title": "Backup-Restore-Test",
            "description": "Quartalstest der Backup-Wiederherstellung fuer kritische Systeme.",
            "category": "bsi",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-FIREWALL",
            "title": "Firewall-Rule-Review",
            "description": "Quartalspruefung aller Firewall-Regeln auf Aktualitaet und Minimalitaet.",
            "category": "bsi",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-LOGGING",
            "title": "Logging-Review",
            "description": "Monatliche Pruefung der Log-Einstellungen und Log-Auswertung.",
            "category": "bsi",
            "priority": "medium",
            "frequency": "monthly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-HAERTUNG",
            "title": "Haertungs-Check",
            "description": "Quartalspruefung der System-Haertung nach BSI-Empfehlungen.",
            "category": "bsi",
            "priority": "medium",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-ZERTIFIKATE",
            "title": "Zertifikats-Erneuerung pruefen",
            "description": "Monatliche Pruefung ablaufender TLS/SSL-Zertifikate.",
            "category": "bsi",
            "priority": "high",
            "frequency": "monthly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-RAUMSICHERHEIT",
            "title": "Raumsicherheit-Pruefung",
            "description": "Jaehrliche Pruefung der physischen Sicherheit der Serverraeume.",
            "category": "bsi",
            "priority": "low",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "BSI-MEDIEN",
            "title": "Medienentsorgung-Kontrolle",
            "description": "Quartalskontrolle der ordnungsgemaessen Entsorgung von Datentraegern.",
            "category": "bsi",
            "priority": "medium",
            "frequency": "quarterly",
            "linked_module": None,
        },

        # ─── ISO 27001 (~8) ──────────────────────────────────────────
        {
            "task_code": "ISO-MGMT-REVIEW",
            "title": "Management-Review",
            "description": "Jaehrliches Management-Review des ISMS gemaess ISO 27001 Kap. 9.3.",
            "category": "iso27001",
            "priority": "critical",
            "frequency": "yearly",
            "linked_module": None,
        },
        {
            "task_code": "ISO-INT-AUDIT",
            "title": "Internes ISMS-Audit",
            "description": "Jaehrliches internes Audit des ISMS gemaess ISO 27001 Kap. 9.2.",
            "category": "iso27001",
            "priority": "critical",
            "frequency": "yearly",
            "linked_module": "audit",
        },
        {
            "task_code": "ISO-KORREKTUR",
            "title": "Korrekturmassnahmen-Review",
            "description": "Quartalspruefung offener Korrekturmassnahmen aus Audits.",
            "category": "iso27001",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "ISO-RISK-OWNER",
            "title": "Risiko-Owner-Review",
            "description": "Quartalspruefung der Risiko-Zuordnungen und Verantwortlichkeiten.",
            "category": "iso27001",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": "risks",
        },
        {
            "task_code": "ISO-KENNZAHLEN",
            "title": "Kennzahlen-Erhebung",
            "description": "Monatliche Erhebung der ISMS-Kennzahlen und KPIs.",
            "category": "iso27001",
            "priority": "medium",
            "frequency": "monthly",
            "linked_module": None,
        },
        {
            "task_code": "ISO-SCOPE",
            "title": "ISMS-Scope-Review",
            "description": "Jaehrliche Ueberpruefung des ISMS-Geltungsbereichs.",
            "category": "iso27001",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": "compliance-scope",
        },
        {
            "task_code": "ISO-POLICY",
            "title": "Policy-Aktualisierung",
            "description": "Jaehrliche Ueberpruefung und Aktualisierung aller ISMS-Policies.",
            "category": "iso27001",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": "document-generator",
        },
        {
            "task_code": "ISO-ZERTIFIZIERUNG",
            "title": "Zertifizierungs-Vorbereitung",
            "description": "Jaehrliche Vorbereitung auf externes Zertifizierungsaudit.",
            "category": "iso27001",
            "priority": "high",
            "frequency": "yearly",
            "linked_module": None,
        },

        # ─── AI Act (~7) ─────────────────────────────────────────────
        {
            "task_code": "AIACT-INVENTAR",
            "title": "KI-Inventar aktualisieren",
            "description": "Quartalsaktualisierung des Inventars aller KI-Systeme im Einsatz.",
            "category": "ai_act",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": "ai-act",
        },
        {
            "task_code": "AIACT-RISIKO",
            "title": "KI-Risikobewertung",
            "description": "Jaehrliche Risikobewertung aller KI-Systeme gemaess EU AI Act.",
            "category": "ai_act",
            "priority": "critical",
            "frequency": "yearly",
            "linked_module": "ai-act",
        },
        {
            "task_code": "AIACT-TRANSPARENZ",
            "title": "Transparenzpflicht-Check",
            "description": "Quartalspruefung der Transparenzpflichten fuer KI-Systeme.",
            "category": "ai_act",
            "priority": "high",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "AIACT-OVERSIGHT",
            "title": "Human-Oversight-Validierung",
            "description": "Halbjaehrliche Validierung der menschlichen Aufsicht ueber KI-Systeme.",
            "category": "ai_act",
            "priority": "high",
            "frequency": "semi_annual",
            "linked_module": None,
        },
        {
            "task_code": "AIACT-BIAS",
            "title": "Bias-Monitoring",
            "description": "Quartalspruefung auf Bias und Diskriminierung in KI-Ausgaben.",
            "category": "ai_act",
            "priority": "medium",
            "frequency": "quarterly",
            "linked_module": None,
        },
        {
            "task_code": "AIACT-SCHULUNG",
            "title": "KI-Schulung Mitarbeiter",
            "description": "Jaehrliche Schulung aller Mitarbeiter zu KI-Kompetenz und AI Act.",
            "category": "ai_act",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": "training",
        },
        {
            "task_code": "AIACT-DOKU",
            "title": "KI-Dokumentations-Review",
            "description": "Jaehrliche Ueberpruefung der technischen Dokumentation aller KI-Systeme.",
            "category": "ai_act",
            "priority": "medium",
            "frequency": "yearly",
            "linked_module": None,
        },
    ]
