"""
Runbooks / docs index API — read-only search and preview (PR1.1).
GET /api/runbooks/search, /api/runbooks/preview, /api/runbooks/raw.
"""
from __future__ import annotations

import re
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query

from .auth import require_auth
from . import docs_store as store

runbooks_router = APIRouter(prefix="/api/runbooks", tags=["runbooks-docs"])


@runbooks_router.get("/status")
async def runbooks_status(
    _auth: str = Depends(require_auth),
):
    """Return docs index status: indexed_files, indexed_chunks, last_indexed_at, docs_root, fts_available."""
    return await store.get_docs_index_status()


def _safe_path(path: str) -> bool:
    """Reject path traversal and non-docs paths."""
    if not path or ".." in path or path.startswith("/"):
        return False
    norm = path.replace("\\", "/").strip()
    return bool(re.match(r"^(docs/|runbook/|release/)?[\w/\-.]+\.md$", norm, re.I))


@runbooks_router.get("/search")
async def runbooks_search(
    q: str = Query(..., min_length=1, max_length=200),
    doc_type: Optional[str] = Query(None, description="runbook | release | spec"),
    limit: int = Query(10, ge=1, le=50),
    _auth: str = Depends(require_auth),
):
    """Search runbooks/docs by full text. Returns path, title, snippet."""
    items = await store.search_docs(q=q, doc_type=doc_type, limit=limit)
    return {"items": items}


@runbooks_router.get("/preview")
async def runbooks_preview(
    path: str = Query(..., description="Relative path, e.g. runbook/rehearsal-v1-30min-checklist.md"),
    _auth: str = Depends(require_auth),
):
    """Get path, title, and sections (heading + excerpt) for a doc."""
    if not _safe_path(path):
        raise HTTPException(status_code=400, detail="Invalid path")
    out = await store.get_preview(path)
    if not out:
        raise HTTPException(status_code=404, detail="Not found")
    return out


@runbooks_router.get("/raw")
async def runbooks_raw(
    path: str = Query(..., description="Relative path to markdown file"),
    _auth: str = Depends(require_auth),
):
    """Get raw markdown content (read-only)."""
    if not _safe_path(path):
        raise HTTPException(status_code=400, detail="Invalid path")
    content = await store.get_raw(path)
    if content is None:
        raise HTTPException(status_code=404, detail="Not found")
    from fastapi.responses import PlainTextResponse
    return PlainTextResponse(content, media_type="text/markdown; charset=utf-8")
