"""{{ display_name }} MCP server — generated by mcpify. Do not hand-edit.

Backfills a store db's `semantic_endpoints` table — mcpify's shared
generation pipeline writes the table's schema but leaves it empty
(vectors are computed here, in the target language, not by mcpify's own
Rust generator — see the plan's embeddings decision). Invoked by
`Dockerfile` before the image is considered usable, and by
`run_generated_tests` (Story P8) before the test suite runs, the same way
v1 sequences `populate-embeddings` before `npm test`.
"""

from __future__ import annotations

import asyncio
import sys
from pathlib import Path

import sqlite_vec

from ..data.store import VERSION_STORE_FILES, open_store_read_write
from .embedding_service import embed


async def populate(db_path: Path) -> int:
    async with open_store_read_write(db_path) as conn:
        cursor = await conn.execute(
            "SELECT operation_id, method, path, summary, description FROM endpoints"
        )
        rows = await cursor.fetchall()

        count = 0
        for row in rows:
            text = " ".join(
                part
                for part in (
                    row["method"],
                    row["path"],
                    row["summary"],
                    row["description"],
                )
                if part
            )
            vector = embed(text)
            blob = sqlite_vec.serialize_float32(vector)
            # sqlite-vec's vec0 virtual tables don't implement conflict
            # resolution (no ON CONFLICT / INSERT OR REPLACE support — a
            # duplicate primary key always raises a UNIQUE constraint error),
            # so re-running this against a db that already has rows requires
            # an explicit delete before each insert to stay idempotent.
            await conn.execute(
                "DELETE FROM semantic_endpoints WHERE operation_id = ?",
                (row["operation_id"],),
            )
            await conn.execute(
                "INSERT INTO semantic_endpoints (operation_id, embedding) "
                "VALUES (?, ?)",
                (row["operation_id"], blob),
            )
            count += 1

        await conn.commit()
        return count


def _targets() -> list[Path]:
    """Which store file(s) to populate: bare invocation targets just
    `mcp_store.db` (the default version), matching every deployment that
    only ever ships that one file (this project's own Dockerfile
    included); an explicit path targets exactly that file; `--all` walks
    every version this project's ledger knows about
    (`data.store.VERSION_STORE_FILES`) — the one-time local backfill
    needed after `mcpify add-version` adds a new version file, since each
    version's `.db` gets its own independent `semantic_endpoints` table.
    """
    args = sys.argv[1:]
    if args and args[0] == "--all":
        return [Path(file_name) for file_name in VERSION_STORE_FILES.values()]
    if args:
        return [Path(args[0])]
    return [Path("mcp_store.db")]


def main() -> None:
    for db_path in _targets():
        count = asyncio.run(populate(db_path))
        print(f"populated {count} embedding(s) in '{db_path}'")


if __name__ == "__main__":
    main()
