"""cortex/api/routes/admin/memory_management.py — Memory management endpoints."""

from __future__ import annotations

import logging
from typing import Any, List, Optional

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

from cortex.api.deps import PREFIX, get_plugin
from cortex.api.models import BulkDeleteRequest, BulkDeleteResponse

logger = logging.getLogger(__name__)


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

    # ---- #752: DELETE /admin/memories ----

    @router.delete(
        f"{PREFIX}/admin/memories",
        response_model=BulkDeleteResponse,
        summary="Bulk delete memories scoped to an owner",
        tags=["admin"],
        operation_id="admin_bulk_delete_memories",
    )
    async def admin_bulk_delete_memories(
        body: BulkDeleteRequest,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> BulkDeleteResponse:
        """Bulk-delete (soft-delete) memories for the given owner_id.

        owner_id is required. category optionally narrows scope. dry_run=true counts without deleting.
        """
        import time as _time
        errors: List[str] = []
        storage = getattr(plugin, "storage", None)
        if storage is None:
            return BulkDeleteResponse(owner_id=body.owner_id, errors=["Storage not available"])
        conn = await storage._get_conn()
        where_parts = ["owner_id = ?", "(is_deleted = 0 OR is_deleted IS NULL)"]
        params: list = [body.owner_id]
        if body.category:
            where_parts.append("category = ?")
            params.append(body.category)
        where_clause = " AND ".join(where_parts)
        if body.dry_run:
            try:
                async with conn.execute(
                    f"SELECT COUNT(*) FROM semantic_claim WHERE {where_clause}", params
                ) as cur:
                    row = await cur.fetchone()
                    would_delete = row[0] if row else 0
            except Exception as exc:
                errors.append(f"Dry-run count failed: {exc}")
                logger.error("admin_bulk_delete dry_run: %s", exc, exc_info=True)
                would_delete = 0
            return BulkDeleteResponse(owner_id=body.owner_id, would_delete=would_delete,
                                      dry_run=True, errors=errors)
        deleted = 0
        try:
            now = _time.strftime("%Y-%m-%dT%H:%M:%SZ", _time.gmtime())
            async with storage._write_lock:
                async with conn.execute(
                    f"SELECT id FROM semantic_claim WHERE {where_clause}", params
                ) as cur:
                    id_rows = await cur.fetchall()
                claim_ids = [r[0] for r in id_rows]
                deleted = len(claim_ids)
                if claim_ids:
                    await conn.execute(
                        f"UPDATE semantic_claim SET is_deleted = 1, deleted_at = ?,"
                        f" status = 'archived', updated_at = ? WHERE {where_clause}",
                        [now, now] + params,
                    )
                    placeholders = ",".join("?" * len(claim_ids))
                    await conn.execute(
                        f"DELETE FROM fts_claims WHERE claim_id IN ({placeholders})",
                        claim_ids,
                    )
                    await conn.commit()
        except Exception as exc:
            errors.append(f"Bulk delete failed: {exc}")
            logger.error("admin_bulk_delete: %s", exc, exc_info=True)
            return BulkDeleteResponse(owner_id=body.owner_id, deleted=0, dry_run=False, errors=errors)
        return BulkDeleteResponse(owner_id=body.owner_id, deleted=deleted, dry_run=False, errors=errors)

    @router.get(
        f"{PREFIX}/admin/orphan-candidates",
        summary="List orphan-candidate memories (mentions=1, older than threshold)",
        tags=["admin"],
        operation_id="admin_orphan_candidates",
    )
    async def admin_orphan_candidates(
        min_age_days: int = 30,
        limit: int = 100,
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ):
        """Return active claims with mentions=1 that are older than min_age_days.

        These are candidates for pruning — claims never re-mentioned that may be stale.
        """
        storage = getattr(plugin, "storage", None)
        if storage is None:
            return JSONResponse({"error": "Storage not available"}, status_code=503)
        eff_owner_id = owner_id or getattr(getattr(plugin, "config", None), "owner_id", "default")
        conn = await storage._get_conn()
        try:
            async with conn.execute(
                """
                SELECT id, owner_id, subject, predicate, object_value,
                       category, confidence, status, created_at, updated_at,
                       mentions, last_mentioned_at
                FROM semantic_claim
                WHERE owner_id = ?
                  AND (is_deleted = 0 OR is_deleted IS NULL)
                  AND status = 'active'
                  AND (mentions = 1 OR mentions IS NULL)
                  AND created_at <= datetime('now', ? || ' days')
                ORDER BY created_at ASC
                LIMIT ?
                """,
                (eff_owner_id, f"-{min_age_days}", limit),
            ) as cur:
                rows = await cur.fetchall()
            items = [
                {
                    "id": r[0],
                    "owner_id": r[1],
                    "subject": r[2],
                    "predicate": r[3],
                    "object_value": r[4],
                    "category": r[5],
                    "confidence": r[6],
                    "status": r[7],
                    "created_at": r[8],
                    "updated_at": r[9],
                    "mentions": r[10] if r[10] is not None else 1,
                    "last_mentioned_at": r[11],
                }
                for r in rows
            ]
            return JSONResponse({
                "items": items,
                "count": len(items),
                "min_age_days": min_age_days,
                "owner_id": eff_owner_id,
            })
        except Exception as exc:
            logger.error("admin_orphan_candidates: %s", exc, exc_info=True)
            return JSONResponse({"error": str(exc)}, status_code=500)
