"""cortex/api/routes/cornerstones.py — Cornerstone endpoints."""

from __future__ import annotations

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

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

from cortex.api.deps import PREFIX, _serialise, get_plugin
from cortex.api.models import ReviseRequest, SealNewRequest, SealRequest

logger = logging.getLogger(__name__)

router = APIRouter()


def _make_routes(verify_api_key):
    """Register cornerstone routes with the given auth dependency."""

    @router.get(
        f"{PREFIX}/cornerstones",
        summary="List all cornerstones",
        tags=["cornerstones"],
        operation_id="list_cornerstones",
    )
    async def list_cornerstones(
        status_filter: Optional[str] = None,
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Return all sealed cornerstone memories with a 200-char content preview."""
        storage = getattr(plugin, "storage", None)
        if storage is not None and hasattr(storage, "get_cornerstones"):
            cs_list = await storage.get_cornerstones(owner_id=owner_id or plugin.config.owner_id)
            items = []
            for cs in cs_list:
                if status_filter and getattr(cs, "status", "") != status_filter:
                    continue
                d = _serialise(cs.__dict__) if hasattr(cs, "__dict__") else _serialise(cs)
                if "content" in d and isinstance(d["content"], str):
                    d["content_preview"] = d["content"][:200]
                items.append(d)
            return JSONResponse(content={"cornerstones": items, "count": len(items)})
        return JSONResponse(content={"cornerstones": [], "total": 0})

    @router.post(
        f"{PREFIX}/cornerstones/{{memory_id}}/seal",
        summary="Seal a memory as a cornerstone",
        tags=["cornerstones"],
        operation_id="seal_cornerstone",
    )
    async def seal_cornerstone(
        memory_id: str,
        body: Optional[SealRequest] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Mark a memory as a protected cornerstone."""
        # Fix 2: Look up the existing claim — if memory_id refers to a known
        # claim, use its data as defaults. If not found and no content was
        # supplied by the caller, return 404.
        label_from_body = body.label if body else None
        content_from_body = (body.content if body else None) or ""
        label = label_from_body or memory_id
        content = content_from_body

        storage = getattr(plugin, "storage", None)
        if storage is not None and hasattr(storage, "get_claim"):
            try:
                existing_claim = await storage.get_claim(memory_id)
                if existing_claim is None and not content_from_body:
                    raise HTTPException(
                        status_code=status.HTTP_404_NOT_FOUND,
                        detail=f"Memory '{memory_id}' not found",
                    )
                if existing_claim is not None:
                    # Use stored claim data as defaults
                    if not content_from_body:
                        content = (
                            f"{existing_claim.subject} "
                            f"{existing_claim.predicate} "
                            f"{existing_claim.object_value}"
                        ).strip()
                    if not label_from_body:
                        label = getattr(existing_claim, "subject", None) or memory_id
            except HTTPException:
                raise
            except Exception as lookup_exc:
                logger.warning(
                    "seal endpoint: claim lookup failed for %r: %s",
                    memory_id,
                    lookup_exc,
                )

        result = await plugin.seal_cornerstone(
            memory_id=memory_id,
            label=label,
            content=content,
        )
        if result is None:
            raise HTTPException(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                detail="CornerstoneGuardian not available",
            )
        data = _serialise(result.__dict__) if hasattr(result, "__dict__") else str(result)
        return JSONResponse(content={"cornerstone": data})

    @router.post(
        f"{PREFIX}/cornerstones/{{memory_id}}/unseal",
        summary="Unseal a cornerstone",
        tags=["cornerstones"],
        operation_id="unseal_cornerstone",
    )
    async def unseal_cornerstone(
        memory_id: str,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Remove cornerstone protection from a memory."""
        result = await plugin.unseal_cornerstone(memory_id=memory_id)
        if result is None:
            raise HTTPException(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                detail="CornerstoneGuardian not available or memory not found",
            )
        data = _serialise(result.__dict__) if hasattr(result, "__dict__") else str(result)
        return JSONResponse(content={"cornerstone": data})

    @router.post(
        f"{PREFIX}/cornerstones",
        summary="Seal a new cornerstone",
        tags=["cornerstones"],
        status_code=status.HTTP_201_CREATED,
        operation_id="create_cornerstone",
    )
    async def create_cornerstone(
        body: SealNewRequest,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Create a new cornerstone memory directly from label + content."""
        storage = getattr(plugin, "storage", None)
        if storage is None:
            raise HTTPException(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                detail="Storage not available",
            )
        owner_id = body.owner_id or plugin.config.owner_id
        try:
            cs = await storage.seal_cornerstone(
                label=body.label,
                content=body.content,
                owner_id=owner_id,
                injection_order=body.injection_order,
            )
            data = _serialise(cs.__dict__) if hasattr(cs, "__dict__") else _serialise(cs)
            return JSONResponse(content={"cornerstone": data}, status_code=201)
        except Exception as exc:
            logger.error("create_cornerstone failed: %s", exc, exc_info=True)
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Internal server error",
            )

    @router.get(
        f"{PREFIX}/cornerstones/{{cs_id}}",
        summary="Cornerstone detail",
        tags=["cornerstones"],
        operation_id="get_cornerstone",
    )
    async def get_cornerstone_detail(
        cs_id: str,
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Return full cornerstone data: content, golden_copy, drift_score, history, changelog."""
        storage = getattr(plugin, "storage", None)
        if storage is None:
            raise HTTPException(503, detail="Storage not available")
        try:
            cs = await storage.get_cornerstone_by_id(cs_id, owner_id=owner_id or plugin.config.owner_id)
            if cs is None:
                raise HTTPException(404, detail=f"Cornerstone {cs_id} not found")
            data = _serialise(cs.__dict__) if hasattr(cs, "__dict__") else _serialise(cs)

            drift_history: List[Dict] = []
            if hasattr(storage, "get_cornerstone_drift_history"):
                drift_history = await storage.get_cornerstone_drift_history(cs_id)

            data["drift_history"] = drift_history
            return JSONResponse(content={"cornerstone": data})
        except HTTPException:
            raise
        except Exception as exc:
            logger.error("get_cornerstone_detail failed: %s", exc, exc_info=True)
            raise HTTPException(500, detail="Internal server error")

    @router.put(
        f"{PREFIX}/cornerstones/{{cs_id}}",
        summary="Revise cornerstone content",
        tags=["cornerstones"],
        operation_id="revise_cornerstone",
    )
    async def revise_cornerstone(
        cs_id: str,
        body: ReviseRequest,
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Update cornerstone content and log the revision to changelog."""
        storage = getattr(plugin, "storage", None)
        if storage is None:
            raise HTTPException(503, detail="Storage not available")
        try:
            existing = await storage.get_cornerstone_by_id(cs_id, owner_id=owner_id or plugin.config.owner_id)
            if existing is None:
                raise HTTPException(404, detail=f"Cornerstone {cs_id} not found")
            if not hasattr(storage, "update_cornerstone_content"):
                raise HTTPException(501, detail="update_cornerstone_content not implemented")
            cs = await storage.update_cornerstone_content(
                cs_id,
                content=body.content,
                reason=body.reason or "manual_revision",
            )
            data = _serialise(cs.__dict__) if hasattr(cs, "__dict__") else _serialise(cs)
            return JSONResponse(content={"cornerstone": data, "revised": True})
        except HTTPException:
            raise
        except Exception as exc:
            logger.error("revise_cornerstone failed: %s", exc, exc_info=True)
            raise HTTPException(500, detail="Internal server error")

    @router.get(
        f"{PREFIX}/cornerstones/{{cs_id}}/drift",
        summary="Cornerstone drift history",
        tags=["cornerstones"],
        operation_id="get_cornerstone_drift",
    )
    async def get_cornerstone_drift(
        cs_id: str,
        limit: int = 50,
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Return drift history for a cornerstone: score, checked_at, action."""
        storage = getattr(plugin, "storage", None)
        if storage is None:
            raise HTTPException(503, detail="Storage not available")
        try:
            existing = await storage.get_cornerstone_by_id(cs_id, owner_id=owner_id or plugin.config.owner_id)
            if existing is None:
                raise HTTPException(404, detail=f"Cornerstone {cs_id} not found")
            if hasattr(storage, "get_cornerstone_drift_history"):
                history = await storage.get_cornerstone_drift_history(cs_id, limit=limit)
                return JSONResponse(content={"drift_history": history})
            return JSONResponse(content={"drift_history": []})
        except HTTPException:
            raise
        except Exception as exc:
            logger.error("get_cornerstone_drift failed: %s", exc, exc_info=True)
            raise HTTPException(500, detail="Internal server error")

    @router.post(
        f"{PREFIX}/cornerstones/{{cs_id}}/restore",
        summary="Restore cornerstone from golden copy",
        tags=["cornerstones"],
        operation_id="restore_cornerstone",
    )
    async def restore_cornerstone_from_golden(
        cs_id: str,
        owner_id: Optional[str] = None,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> JSONResponse:
        """Restore cornerstone content to its original golden_copy."""
        storage = getattr(plugin, "storage", None)
        if storage is None:
            raise HTTPException(503, detail="Storage not available")
        try:
            existing = await storage.get_cornerstone_by_id(cs_id, owner_id=owner_id or plugin.config.owner_id)
            if existing is None:
                raise HTTPException(404, detail=f"Cornerstone {cs_id} not found")
            cs = await storage.restore_cornerstone(cs_id)
            data = _serialise(cs.__dict__) if hasattr(cs, "__dict__") else _serialise(cs)
            return JSONResponse(content={"cornerstone": data, "restored": True})
        except HTTPException:
            raise
        except Exception as exc:
            logger.error("restore_cornerstone failed: %s", exc, exc_info=True)
            raise HTTPException(500, detail="Internal server error")
