from pathlib import Path
from sqlite3 import Connection as SQLiteConnection
from typing import Protocol, cast

import aiosql.queries

from renkon.repo.info import FileType, TableDBTuple


class RegistryQueries(Protocol):  # pragma: no cover
    """
    Protocol for the queries used by the registry. This allows us to define a typed interface
    for the queries supported by the registry, and also to support mocking use of the queries in
    tests without any actual database.

    Warning: if the types in this class are changed, the corresponding types in registry.sql must
    also be changed.
    """

    def create_tables(self, conn: SQLiteConnection) -> None:
        ...

    def register_table(
        self, conn: SQLiteConnection, *, path: str, name: str, filetype: str, schema: bytes, rows: int, size: int
    ) -> None:
        ...

    def unregister_table(self, conn: SQLiteConnection, *, name: str) -> None:
        ...

    def get_table(self, conn: SQLiteConnection, *, name: str, filetype: FileType) -> TableDBTuple:
        ...

    def get_table_by_path(self, conn: SQLiteConnection, *, path: str) -> TableDBTuple:
        ...

    def list_tables(self, conn: SQLiteConnection) -> list[TableDBTuple]:
        ...

    def search_tables_by_path(self, conn: SQLiteConnection, *, path: str) -> list[TableDBTuple]:
        ...

    def search_tables_by_name(self, conn: SQLiteConnection, *, name: str) -> list[TableDBTuple]:
        ...


class Queries(aiosql.queries.Queries, RegistryQueries):  # type: ignore[misc] # pragma: no cover
    """
    Queries for the repository.

    These methods do not define the logic for the queries, but rather the interface for the
    queries. This is in order to provide type hints for the queries. The actual logic is
    generated by AIOSQL at runtime. The queries are defined in repository.sql.
    """


queries: Queries = cast(
    Queries, aiosql.from_path(sql_path=Path(__file__).with_name("registry.sql"), driver_adapter="sqlite3")
)
