import time

from quart import Blueprint, jsonify, request

from scribe.auth import login_required, get_current_user_id
from scribe.services.access import owner_names_for
from scribe.services.embeddings import (
    INTERACTIVE_SEARCH_THRESHOLD as _REST_SEARCH_THRESHOLD,
)
from scribe.services.embeddings import semantic_search_notes
from scribe.services.retrieval_telemetry import record_retrieval

# The interactive floor lives in embeddings.py now, shared with Browse search
# and the list views' semantic `q` — one number, one rationale (#2463).

search_bp = Blueprint("search", __name__, url_prefix="/api/search")


def _content_type_to_is_task(content_type: str) -> bool | None:
    """Map content_type query param to semantic_search_notes is_task arg."""
    if content_type == "note":
        return False
    if content_type == "task":
        return True
    return None  # "all" or unknown → no filter


@search_bp.route("", methods=["GET"])
@login_required
async def search_route():
    uid = get_current_user_id()
    q = (request.args.get("q") or "").strip()
    if not q:
        return jsonify({"error": "q is required"}), 400

    content_type = request.args.get("content_type", "all")
    limit = min(request.args.get("limit", 10, type=int), 50)
    is_task = _content_type_to_is_task(content_type)
    # Same association filters the MCP tool takes (#33). Optional, default
    # global: this route has NO frontend consumer today (measured 2026-08-08 —
    # the web UI searches through /api/knowledge), so it serves API callers,
    # and an API caller states its scope explicitly.
    system_id = request.args.get("system_id", type=int)
    project_id = request.args.get("project_id", type=int)

    t0 = time.perf_counter()
    results = await semantic_search_notes(
        uid, q, limit=limit, is_task=is_task, threshold=_REST_SEARCH_THRESHOLD,
        project_id=project_id, system_id=system_id,
        # The user typed this, so it reaches everything they may read.
        scope="read",
    )
    record_retrieval(
        user_id=uid, source="rest_search", query=q,
        threshold=_REST_SEARCH_THRESHOLD, limit=limit,
        project_id=project_id, is_task=is_task, results=results,
        duration_ms=(time.perf_counter() - t0) * 1000.0,
    )
    owners = await owner_names_for(
        {int(note.user_id) for _s, note in results if note.user_id != uid}
    )
    return jsonify({
        "results": [
            {
                "id": note.id,
                "title": note.title,
                "body": note.body or "",
                "is_task": note.is_task,
                "tags": note.tags or [],
                "similarity": score,
                **(
                    {"shared": True, "owner": owners.get(int(note.user_id))}
                    if note.user_id != uid else {}
                ),
            }
            for score, note in results  # semantic_search_notes returns list[tuple[float, Note]]
        ],
        "total": len(results),
    })
