"""cortex/api/routes/admin/dreams.py — Dream cycle admin endpoint."""

from __future__ import annotations

import logging
from typing import Any, List, Optional

from fastapi import APIRouter, Depends, Request
from fastapi.responses import JSONResponse

from cortex.api.deps import PREFIX, _resolve_owner_id, get_plugin
from cortex.storage.migrations.v26_orphan_sessions import _MARK_ORPHANS_SQL

logger = logging.getLogger(__name__)


def _register(router: APIRouter, verify_api_key):
    """Register dream cycle routes on the given router."""

    @router.post(
        f"{PREFIX}/admin/dream-cycle",
        summary="Manually trigger a dream cycle (admin)",
        tags=["admin"],
        operation_id="admin_dream_cycle",
    )
    async def admin_dream_cycle(
        request: Request,
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ):
        """Trigger a full dream cycle manually — for ops/debugging.

        Returns cycle status, memories processed count, and duration_ms.

        Security fix (#1526): owner_id is resolved from auth middleware
        rather than trusting the request body/query parameter.
        """
        import time as _time

        t0 = _time.monotonic()
        errors: List[str] = []
        _owner = _resolve_owner_id(request, owner_id)

        try:
            dream_report = await plugin.dream(owner_id=_owner)
            duration_ms = int((_time.monotonic() - t0) * 1000)
            memories_processed = (
                getattr(dream_report, "claims_consolidated", 0)
                or getattr(dream_report, "steps_completed", 0)
                or 0
            )
            return JSONResponse(content={
                "status": "completed",
                "memories_processed": memories_processed,
                "duration_ms": duration_ms,
                "steps_completed": getattr(dream_report, "steps_completed", 0),
                "curiosity_seeds": getattr(dream_report, "curiosity_seeds", 0),
                "journal": getattr(dream_report, "journal", ""),
                "errors": getattr(dream_report, "errors", []),
            })
        except Exception as exc:
            err = f"Dream cycle failed: {exc}"
            logger.error(err, exc_info=True)
            errors.append(err)
            duration_ms = int((_time.monotonic() - t0) * 1000)
            return JSONResponse(
                status_code=500,
                content={
                    "status": "failed",
                    "memories_processed": 0,
                    "duration_ms": duration_ms,
                    "errors": errors,
                },
            )

    @router.post(
        f"{PREFIX}/admin/mark-orphan-sessions",
        summary="Mark claimless batch-ingest sessions as orphan (R-321)",
        tags=["admin"],
        operation_id="admin_mark_orphan_sessions",
    )
    async def admin_mark_orphan_sessions(
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ):
        """Mark claimless batch-ingest sessions as status='orphan'.

        Targets sessions that:
        - Have 0 associated semantic_claims (source_session FK never matched)
        - Were created by batch ingest (session_id starts with 'batch-' or
          looks like an ISO date e.g. '2026-03-12')
        - Are not currently active (not 'awake')

        This is a one-time ops endpoint to clean up the 3,084 orphan sessions
        created by the batch ingest pipeline (R-321). Safe to run multiple times
        (idempotent). The dream pipeline skips sessions with status='orphan'.
        """
        try:
            storage = plugin.storage
            conn = await storage.get_connection()
            cursor = await conn.execute(_MARK_ORPHANS_SQL)
            await conn.commit()
            rows_updated = cursor.rowcount
            return JSONResponse(content={
                "status": "ok",
                "sessions_marked_orphan": rows_updated,
                "message": (
                    f"Marked {rows_updated} claimless batch-ingest session(s) as orphan. "
                    "Dream pipeline will skip these sessions."
                ),
            })
        except Exception as exc:
            err = f"Mark orphan sessions failed: {exc}"
            logger.error(err, exc_info=True)
            return JSONResponse(
                status_code=500,
                content={"status": "failed", "error": err},
            )
