"""
admin.py
--------
Administrative and governance endpoints for the HIEROMEM API.
"""

from __future__ import annotations

from typing import Any

from fastapi import APIRouter, Depends, HTTPException

from hieromem_api.deps import get_memory_engine
from hieromem_api.models.requests import ParamUpdateRequest
from hieromem_api.models.responses import GSRViewResponse, ParamUpdateResponse
from hieromem_api.services.governance_service import GovernanceService
from hieromem_api.auth import require_api_key, require_permission
from hieromem_api.rbac import Permission
from hieromem_api.tenants import Tenant

router = APIRouter(prefix="/admin", tags=["Admin"])

memory = get_memory_engine()


def _governance_service() -> GovernanceService:
    gsr = getattr(memory, "gsr", None)
    if gsr is None:
        raise HTTPException(status_code=503,
                            detail="Governance module unavailable")
    return GovernanceService(gsr)


@router.get("/gsr", response_model=GSRViewResponse)
def gsr_view(
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.MANAGE_TENANT)),
) -> GSRViewResponse:
    """Return the current Governance Safety Region state and validity."""

    try:
        service = _governance_service()
        return service.snapshot()
    except Exception as exc:  # pragma: no cover - FastAPI will surface HTTPException
        raise HTTPException(status_code=500,
                            detail=f"GSR view failed: {exc}") from exc


@router.post("/update", response_model=ParamUpdateResponse)
def update_params(
    req: ParamUpdateRequest,
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.MANAGE_TENANT)),
) -> ParamUpdateResponse:
    """Dynamically update governance parameters with validation."""

    try:
        updates = req.model_dump(exclude_none=True)
        if not updates:
            raise HTTPException(status_code=400,
                                detail="No parameters provided for update.")
        service = _governance_service()
        response = service.update(updates)
        for key, value in updates.items():
            if hasattr(memory, key):
                setattr(memory, key, value)
        return response
    except HTTPException:
        raise
    except Exception as exc:  # pragma: no cover - FastAPI will surface HTTPException
        raise HTTPException(status_code=500,
                            detail=f"Update failed: {exc}") from exc


@router.post("/summarize")
def force_summarization(
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.MANAGE_TENANT)),
) -> dict[str, str]:
    """Trigger summarization manually to compact memory and enforce bounded growth."""

    try:
        memory.summarise()
        return {
            "status": "ok",
            "message": "Summarization triggered successfully."}
    except Exception as exc:  # pragma: no cover - FastAPI will surface HTTPException
        raise HTTPException(status_code=500,
                            detail=f"Summarization failed: {exc}") from exc


@router.post("/decay")
def force_decay(
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.MANAGE_TENANT)),
) -> dict[str, str]:
    """Trigger a full trust decay pass on all episodes."""

    try:
        memory.update_trust()
        return {
            "status": "ok",
            "message": "Trust decay executed successfully."}
    except Exception as exc:  # pragma: no cover - FastAPI will surface HTTPException
        raise HTTPException(status_code=500,
                            detail=f"Decay failed: {exc}") from exc


@router.get("/dump")
def dump_state(
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.MANAGE_TENANT)),
) -> dict[str, Any]:
    """Export current memory state (IDs, trust, timestamps)."""

    try:
        episodes = [
            {
                "id": ep.id,
                "trust": float(ep.trust),
                "timestamp": ep.tocc.isoformat(),
                "meta": ep.meta,
            }
            for ep in getattr(memory, "episodes", [])
        ]
        return {"count": len(episodes), "episodes": episodes}
    except Exception as exc:  # pragma: no cover - FastAPI will surface HTTPException
        raise HTTPException(
            status_code=500,
            detail=f"Dump failed: {exc}") from exc
