"""DatabaseAdapter protocol — interface every adapter must implement."""

from __future__ import annotations

from typing import Any, Protocol, runtime_checkable

import numpy as np


@runtime_checkable
class DatabaseAdapter(Protocol):
    """Protocol that each database adapter must satisfy."""

    @property
    def name(self) -> str:
        """Short identifier for this database (e.g. 'age', 'neo4j')."""
        ...

    def connect(self) -> None:
        """Establish a connection to the database."""
        ...

    def close(self) -> None:
        """Close the database connection and release resources."""
        ...

    def setup_schema(self, vec_dims: int) -> None:
        """Create graph schema, indexes, and vector tables as needed."""
        ...

    def teardown(self) -> None:
        """Drop all benchmark data (graph, tables, spaces)."""
        ...

    # -- Data loading ----------------------------------------------------

    def load_nodes(
        self,
        nodes: list[dict[str, Any]],
    ) -> int:
        """Load nodes into the database. Returns count loaded."""
        ...

    def load_edges(
        self,
        edges: list[dict[str, Any]],
    ) -> int:
        """Load edges into the database. Returns count loaded."""
        ...

    # -- Workloads -------------------------------------------------------

    def w01_node_creation(self, nodes: list[dict[str, Any]]) -> int:
        """W01: Create nodes one-by-one via Cypher/nGQL. Returns count."""
        ...

    def w02_edge_creation(self, edges: list[dict[str, Any]]) -> int:
        """W02: Create edges one-by-one. Returns count."""
        ...

    def w03_point_lookup(self, node_id: int) -> dict[str, Any] | None:
        """W03: Lookup a single node by its benchmark ID. Returns properties."""
        ...

    def w04_pattern_match(self, hops: int, start_id: int = 0) -> int:
        """W04: N-hop pattern match from a start node. Returns row count."""
        ...

    def w05_aggregation(self) -> list[dict[str, Any]]:
        """W05: Group-by aggregation (count per label/category). Returns rows."""
        ...

    def w06_vle(self, min_hops: int, max_hops: int, start_id: int = 0) -> int:
        """W06: Variable-length edge traversal. Returns path count."""
        ...

    def w07_shortest_path(self, start_id: int, end_id: int) -> int:
        """W07: Shortest path between two nodes. Returns path length."""
        ...

    def w08_pagerank(self, iterations: int) -> list[dict[str, Any]]:
        """W08: PageRank (or equivalent). Returns top-10 nodes with scores."""
        ...

    def w09_vector_search(self, query_vec: np.ndarray, k: int) -> int:
        """W09: k-NN vector search. Returns result count."""
        ...

    def w10_hybrid_search(
        self, query_vec: np.ndarray, k: int, label: str
    ) -> int:
        """W10: Graph-filtered vector search. Returns result count."""
        ...

    def w11_bulk_load(self, nodes: list[dict[str, Any]], edges: list[dict[str, Any]]) -> int:
        """W11: Bulk load (fastest path available). Returns total count."""
        ...

    def w12_concurrent(self, queries: list[str], concurrency: int) -> float:
        """W12: Concurrent query throughput. Returns queries/sec."""
        ...
