"""cortex/api/routes/peers.py — Peer modeling 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 PeerCreateRequest, PeerPatchRequest, PeerRebuildRequest

logger = logging.getLogger(__name__)

router = APIRouter()


def _peer_to_dict(peer: Any) -> Dict[str, Any]:
    import json as _json
    try:
        rep = _json.loads(peer.representation or "{}")
    except Exception:
        rep = {}
    return {
        "id": peer.id,
        "owner_id": peer.owner_id,
        "entity_id": peer.entity_id,
        "display_name": peer.display_name,
        "relationship": peer.relationship,
        "first_interaction": peer.first_interaction,
        "last_interaction": peer.last_interaction,
        "interaction_count": peer.interaction_count,
        "representation": rep,
        "created_at": peer.created_at,
        "updated_at": peer.updated_at,
    }


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

    @router.get(f"{PREFIX}/peers", summary="List peers", tags=["peers"])
    async def list_peers(
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> Dict[str, Any]:
        """List all peers for the configured owner."""
        if plugin.storage is None:
            raise HTTPException(status_code=503, detail="Storage unavailable")
        peers = await plugin.storage.list_peers(owner_id=plugin.config.owner_id)
        return {"peers": [_peer_to_dict(p) for p in peers], "total": len(peers)}

    @router.get(f"{PREFIX}/peers/{{peer_id}}", summary="Get peer detail", tags=["peers"])
    async def get_peer_detail(
        peer_id: str,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> Dict[str, Any]:
        """Fetch a peer by ID including full representation."""
        if plugin.storage is None:
            raise HTTPException(status_code=503, detail="Storage unavailable")
        peer = await plugin.storage.get_peer(peer_id)
        if peer is None:
            raise HTTPException(status_code=404, detail=f"Peer not found: {peer_id}")
        return _peer_to_dict(peer)

    @router.post(f"{PREFIX}/peers", summary="Create peer", tags=["peers"], status_code=201)
    async def create_peer(
        body: PeerCreateRequest,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> Dict[str, Any]:
        """Manually create a peer."""
        if plugin.storage is None:
            raise HTTPException(status_code=503, detail="Storage unavailable")
        owner_id = body.owner_id or plugin.config.owner_id
        peer = await plugin.storage.create_peer(
            owner_id=owner_id,
            display_name=body.display_name,
            entity_id=body.entity_id,
            relationship=body.relationship,
        )
        return _peer_to_dict(peer)

    @router.patch(f"{PREFIX}/peers/{{peer_id}}", summary="Update peer", tags=["peers"])
    async def update_peer(
        peer_id: str,
        body: PeerPatchRequest,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> Dict[str, Any]:
        """Update display_name, entity_id, or relationship."""
        if plugin.storage is None:
            raise HTTPException(status_code=503, detail="Storage unavailable")
        existing = await plugin.storage.get_peer(peer_id)
        if existing is None:
            raise HTTPException(status_code=404, detail=f"Peer not found: {peer_id}")
        updates = {k: v for k, v in body.model_dump().items() if v is not None}
        peer = await plugin.storage.update_peer(peer_id, **updates)
        return _peer_to_dict(peer)

    @router.delete(f"{PREFIX}/peers/{{peer_id}}", summary="Delete peer", tags=["peers"])
    async def delete_peer(
        peer_id: str,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> Dict[str, Any]:
        """Delete a peer by ID."""
        if plugin.storage is None:
            raise HTTPException(status_code=503, detail="Storage unavailable")
        existing = await plugin.storage.get_peer(peer_id)
        if existing is None:
            raise HTTPException(status_code=404, detail=f"Peer not found: {peer_id}")
        await plugin.storage.delete_peer(peer_id)
        return {"deleted": peer_id}

    @router.post(
        f"{PREFIX}/peers/{{peer_id}}/rebuild",
        summary="Rebuild peer representation",
        tags=["peers"],
    )
    async def rebuild_peer_representation(
        peer_id: str,
        body: PeerRebuildRequest,
        _: None = Depends(verify_api_key),
        plugin: Any = Depends(get_plugin),
    ) -> Dict[str, Any]:
        """Rebuild peer representation from supplied claims."""
        if plugin.storage is None:
            raise HTTPException(status_code=503, detail="Storage unavailable")
        existing = await plugin.storage.get_peer(peer_id)
        if existing is None:
            raise HTTPException(status_code=404, detail=f"Peer not found: {peer_id}")

        from cortex.peers import PeerManager

        mgr = PeerManager(storage=plugin.storage)

        class _ClaimProxy:
            def __init__(self, d: Dict[str, Any]) -> None:
                self.predicate = d.get("predicate", "")
                self.object_value = d.get("object_value", d.get("content", ""))

        proxies = [_ClaimProxy(c) for c in body.claims]
        rep = await mgr.build_representation(peer_id, proxies)
        return {"peer_id": peer_id, "representation": rep}
