"""
temporal.py
-----------
API routes for temporal queries and sequence reconstruction.
"""

from __future__ import annotations

from datetime import datetime
from typing import Literal, Optional

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field

from hieromem_api.auth import require_api_key, require_permission
from hieromem_api.deps import get_memory_engine
from hieromem_api.rbac import Permission
from hieromem_api.tenants import Tenant, canonical_namespace, resolve_tenant
from hieromem_core.episode import Episode
from hieromem_core.reasoning.sequence import reconstruct_sequence
from hieromem_core.reasoning.temporal import episodes_after, episodes_before, episodes_in_range

router = APIRouter(prefix="/temporal", tags=["Temporal"])

memory = get_memory_engine()


class TemporalRangeRequest(BaseModel):
    start: Optional[datetime] = None
    end: Optional[datetime] = None
    limit: int = Field(50, ge=0)
    order: Literal["asc", "desc"] = "asc"
    namespace: Optional[str] = None


class TemporalAnchorRequest(BaseModel):
    anchor_episode_id: str
    direction: Literal["before", "after"] = "before"
    limit: int = Field(20, ge=0)
    namespace: Optional[str] = None


class TemporalSequenceRequest(BaseModel):
    start_episode_id: Optional[str] = None
    end_episode_id: Optional[str] = None
    limit: int = Field(100, ge=0)
    namespace: Optional[str] = None


class EpisodeTimeSummary(BaseModel):
    id: str
    timestamp: str
    trust: float
    meta: dict


def _summarize(ep: Episode) -> EpisodeTimeSummary:
    meta = ep.meta if isinstance(ep.meta, dict) else {}
    return EpisodeTimeSummary(
        id=ep.id,
        timestamp=ep.tocc.isoformat(),
        trust=float(ep.trust),
        meta=meta,
    )


@router.post("/range", response_model=list[EpisodeTimeSummary])
def range_query(
    req: TemporalRangeRequest,
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.READ_MEMORY)),
) -> list[EpisodeTimeSummary]:
    tenant = resolve_tenant(tenant)
    namespace = canonical_namespace(tenant, req.namespace)
    with memory.use_namespace(namespace):
        episodes = episodes_in_range(
            memory.episodes,
            req.start,
            req.end,
            limit=req.limit,
            ascending=req.order == "asc",
        )
    return [_summarize(ep) for ep in episodes]


@router.post("/anchor", response_model=list[EpisodeTimeSummary])
def anchor_query(
    req: TemporalAnchorRequest,
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.READ_MEMORY)),
) -> list[EpisodeTimeSummary]:
    tenant = resolve_tenant(tenant)
    namespace = canonical_namespace(tenant, req.namespace)
    with memory.use_namespace(namespace):
        anchor = memory._get_episode_by_id(req.anchor_episode_id)
        if anchor is None:
            raise HTTPException(status_code=404, detail="Episode not found")
        if req.direction == "before":
            episodes = episodes_before(memory.episodes, anchor.tocc, limit=req.limit)
        else:
            episodes = episodes_after(memory.episodes, anchor.tocc, limit=req.limit)
    return [_summarize(ep) for ep in episodes]


@router.post("/sequence", response_model=list[EpisodeTimeSummary])
def sequence_query(
    req: TemporalSequenceRequest,
    tenant: Tenant = Depends(require_api_key),
    _perm_check: None = Depends(require_permission(Permission.READ_MEMORY)),
) -> list[EpisodeTimeSummary]:
    tenant = resolve_tenant(tenant)
    namespace = canonical_namespace(tenant, req.namespace)
    episodes = reconstruct_sequence(
        memory,
        start_episode_id=req.start_episode_id,
        end_episode_id=req.end_episode_id,
        limit=req.limit,
        namespace=namespace,
    )
    return [_summarize(ep) for ep in episodes]
