"""MemoTrail REST API — /api/v1/ routes."""

from fastapi import APIRouter, Query
from pydantic import BaseModel

from memotrail.storage import SQLiteStore, ChromaStore
from memotrail.core.searcher import Searcher
from memotrail.core.embedder import Embedder
from memotrail.core.context_packer import ContextPacker
from memotrail.core.graph import KnowledgeGraph
from memotrail.core.temporal import TemporalTracker
from memotrail.utils import get_logger

logger = get_logger("memotrail.web.api")

# Shared instances (will be set by mount_api)
_sqlite: SQLiteStore | None = None
_chroma: ChromaStore | None = None
_searcher: Searcher | None = None
_context_packer: ContextPacker | None = None
_graph: KnowledgeGraph | None = None
_temporal: TemporalTracker | None = None

router = APIRouter(prefix="/api/v1")


def mount_api(
    sqlite_store: SQLiteStore,
    chroma_store: ChromaStore,
    searcher: Searcher,
    context_packer: ContextPacker,
    graph: KnowledgeGraph,
    temporal: TemporalTracker,
) -> None:
    """Initialize shared instances for API routes."""
    global _sqlite, _chroma, _searcher, _context_packer, _graph, _temporal
    _sqlite = sqlite_store
    _chroma = chroma_store
    _searcher = searcher
    _context_packer = context_packer
    _graph = graph
    _temporal = temporal


# ── Request/Response models ─────────────────────────────────

class SearchRequest(BaseModel):
    query: str
    limit: int = 10
    project: str | None = None
    method: str = "semantic"  # semantic, keyword, hybrid


class ContextRequest(BaseModel):
    query: str
    project: str | None = None
    budget: int | None = None


class MemoryCreateRequest(BaseModel):
    content: str
    tags: list[str] = []


# ── Search ──────────────────────────────────────────────────

@router.post("/search")
async def api_search(req: SearchRequest):
    """Search conversations (semantic/keyword/hybrid)."""
    if req.method == "keyword":
        results = _searcher.search_keyword(req.query, limit=req.limit, project=req.project)
    elif req.method == "hybrid":
        results = _searcher.search_hybrid(req.query, limit=req.limit, project=req.project)
    else:
        results = _searcher.search_chats(req.query, limit=req.limit, project=req.project)

    return {
        "query": req.query,
        "method": req.method,
        "count": len(results),
        "results": [
            {
                "chunk_text": r.chunk_text,
                "score": r.score,
                "session_id": r.session_id,
                "project": r.project,
                "timestamp": r.timestamp,
                "session_summary": r.session_summary,
            }
            for r in results
        ],
    }


# ── Sessions ────────────────────────────────────────────────

@router.get("/sessions")
async def api_sessions(
    page: int = Query(1, ge=1),
    per_page: int = Query(20, ge=1, le=100),
    project: str | None = None,
):
    """List sessions with pagination."""
    sessions, total = _sqlite.get_sessions_paginated(page, per_page, project)
    return {
        "page": page,
        "per_page": per_page,
        "total": total,
        "sessions": [
            {
                "id": s.id,
                "project": s.project,
                "started_at": s.started_at,
                "ended_at": s.ended_at,
                "summary": s.summary,
                "message_count": s.message_count,
                "source": s.source,
                "tags": s.tags,
            }
            for s in sessions
        ],
    }


@router.get("/sessions/{session_id}")
async def api_session_detail(session_id: str):
    """Get session detail with messages."""
    session = _sqlite.get_session(session_id)
    if not session:
        return {"error": "Session not found"}, 404

    messages = _sqlite.get_session_messages(session_id)
    return {
        "id": session.id,
        "project": session.project,
        "started_at": session.started_at,
        "ended_at": session.ended_at,
        "summary": session.summary,
        "message_count": session.message_count,
        "source": session.source,
        "tags": session.tags,
        "messages": [
            {
                "id": m.id,
                "role": m.role,
                "content": m.content,
                "timestamp": m.timestamp,
                "token_count": m.token_count,
            }
            for m in messages[:200]
        ],
    }


# ── Decisions ───────────────────────────────────────────────

@router.get("/decisions")
async def api_decisions(
    project: str | None = None,
    limit: int = Query(20, ge=1, le=100),
):
    """List decisions."""
    decisions = _sqlite.get_decisions(project=project, limit=limit)
    return {
        "count": len(decisions),
        "decisions": [
            {
                "id": d.id,
                "session_id": d.session_id,
                "decision_text": d.decision_text,
                "context": d.context,
                "category": d.category,
                "created_at": d.created_at,
            }
            for d in decisions
        ],
    }


# ── Memories ────────────────────────────────────────────────

@router.post("/memories")
async def api_create_memory(req: MemoryCreateRequest):
    """Create a new memory."""
    from memotrail.core.indexer import Indexer

    idx = Indexer(_sqlite, _chroma, embedder=Embedder())
    memory_id, action = idx.index_memory(req.content, req.tags)
    return {"memory_id": memory_id, "action": action.value}


@router.get("/memories")
async def api_list_memories():
    """List all memories."""
    memories = _sqlite.get_all_memories()
    return {"count": len(memories), "memories": memories}


@router.delete("/memories/{memory_id}")
async def api_delete_memory(memory_id: str):
    """Delete a memory."""
    _sqlite.delete_memory(memory_id)
    _chroma.delete_by_ids([memory_id], collection=ChromaStore.MEMORY_COLLECTION)
    return {"deleted": memory_id}


# ── Context ─────────────────────────────────────────────────

@router.post("/context")
async def api_context(req: ContextRequest):
    """Get auto-assembled context for a query."""
    text = _context_packer.pack_query_context(
        req.query, project=req.project, budget=req.budget,
    )
    return {"query": req.query, "context": text}


# ── Graph ───────────────────────────────────────────────────

@router.get("/graph/entities")
async def api_graph_entities(
    entity_type: str | None = None,
    limit: int = Query(100, ge=1, le=500),
):
    """List entities, optionally filtered by type."""
    if entity_type:
        entities = _graph.get_entities_by_type(entity_type, limit=limit)
    else:
        entities = _graph.get_all_entities(limit=limit)
    return {"count": len(entities), "entities": entities}


@router.get("/graph/entity/{name}")
async def api_graph_entity(name: str):
    """Get entity with relations."""
    entity = _graph.get_entity(name)
    if not entity:
        return {"error": f"Entity not found: {name}"}
    return entity


# ── Temporal ────────────────────────────────────────────────

@router.get("/history/{fact_id}")
async def api_fact_history(fact_id: str):
    """Get change history for a fact."""
    history = _temporal.get_fact_history(fact_id)
    return {
        "fact_id": fact_id,
        "count": len(history),
        "history": history,
    }


# ── Stats ───────────────────────────────────────────────────

@router.get("/stats")
async def api_stats():
    """System statistics."""
    db_stats = _sqlite.get_stats()
    chat_chunks = _chroma.get_collection_count(ChromaStore.CHAT_COLLECTION)
    memory_chunks = _chroma.get_collection_count(ChromaStore.MEMORY_COLLECTION)

    try:
        entity_count = _sqlite.conn.execute(
            "SELECT COUNT(*) as c FROM entities"
        ).fetchone()["c"]
        relation_count = _sqlite.conn.execute(
            "SELECT COUNT(*) as c FROM relations"
        ).fetchone()["c"]
    except Exception:
        entity_count = 0
        relation_count = 0

    return {
        **db_stats,
        "chat_chunks": chat_chunks,
        "memory_notes": memory_chunks,
        "total_entities": entity_count,
        "total_relations": relation_count,
    }
