import re
import sys
import types
from _typeshed import Incomplete, StrOrBytesPath
from sqlite3 import Connection as _Connection
from typing import Any, ClassVar, overload

from pony.orm import dbapiprovider, dbschema
from pony.orm.dbapiprovider import DBAPIProvider, Pool
from pony.orm.sqlbuilding import SQLBuilder, Value
from pony.orm.sqltranslation import SQLTranslator
from pony.utils import localbase

class SqliteExtensionUnavailable(Exception): ...

NoneType: type[None]

class SQLiteForeignKey(dbschema.ForeignKey):
    def get_create_command(foreign_key) -> None: ...

class SQLiteSchema(dbschema.DBSchema):
    dialect: ClassVar[str]
    fk_class: ClassVar[type[SQLiteForeignKey]]

def make_overriden_string_func(sqlop): ...

class SQLiteTranslator(SQLTranslator):
    dialect: ClassVar[str]
    sqlite_version: tuple[int, int, int]
    StringMixin_UPPER: Incomplete
    StringMixin_LOWER: Incomplete

class SQLiteValue(Value):
    __slots__: list[str] = []

class SQLiteBuilder(SQLBuilder):
    dialect: ClassVar[str]
    least_func_name: ClassVar[str]
    greatest_func_name: ClassVar[str]
    value_class: ClassVar[type[SQLiteValue]]
    def __init__(builder, provider, ast) -> None: ...
    def SELECT_FOR_UPDATE(builder, nowait, skip_locked, *sections): ...
    def INSERT(builder, table_name, columns, values, returning=None): ...
    def STRING_SLICE(builder, expr, start, stop): ...
    def IN(builder, expr1, x): ...
    def NOT_IN(builder, expr1, x): ...
    def TODAY(builder): ...
    def NOW(builder): ...
    def YEAR(builder, expr): ...
    def MONTH(builder, expr): ...
    def DAY(builder, expr): ...
    def HOUR(builder, expr): ...
    def MINUTE(builder, expr): ...
    def SECOND(builder, expr): ...
    def datetime_add(builder, funcname, expr, td): ...
    def DATE_ADD(builder, expr, delta): ...
    def DATE_SUB(builder, expr, delta): ...
    def DATE_DIFF(builder, expr1, expr2): ...
    def DATETIME_ADD(builder, expr, delta): ...
    def DATETIME_SUB(builder, expr, delta): ...
    def DATETIME_DIFF(builder, expr1, expr2): ...
    def RANDOM(builder): ...
    PY_UPPER: Incomplete
    PY_LOWER: Incomplete
    def FLOAT_EQ(builder, a, b): ...
    def FLOAT_NE(builder, a, b): ...
    def JSON_QUERY(builder, expr, path): ...
    json_value_type_mapping: Incomplete
    def JSON_VALUE(builder, expr, path, type): ...
    def JSON_NONZERO(builder, expr): ...
    def JSON_ARRAY_LENGTH(builder, value): ...
    def JSON_CONTAINS(builder, expr, path, key): ...
    def ARRAY_INDEX(builder, col, index): ...
    def ARRAY_CONTAINS(builder, key, not_in, col): ...
    def ARRAY_SUBSET(builder, array1, not_in, array2): ...
    def ARRAY_LENGTH(builder, array): ...
    def ARRAY_SLICE(builder, array, start, stop): ...
    def MAKE_ARRAY(builder, *items): ...

class SQLiteIntConverter(dbapiprovider.IntConverter):
    def sql_type(converter): ...

class SQLiteDecimalConverter(dbapiprovider.DecimalConverter):
    inf: Incomplete
    neg_inf: Incomplete
    NaN: Incomplete
    def sql2py(converter, val): ...
    def py2sql(converter, val): ...

class SQLiteDateConverter(dbapiprovider.DateConverter):
    def sql2py(converter, val): ...
    def py2sql(converter, val): ...

class SQLiteTimeConverter(dbapiprovider.TimeConverter):
    def sql2py(converter, val): ...
    def py2sql(converter, val): ...

class SQLiteTimedeltaConverter(dbapiprovider.TimedeltaConverter):
    def sql2py(converter, val): ...
    def py2sql(converter, val): ...

class SQLiteDatetimeConverter(dbapiprovider.DatetimeConverter):
    def sql2py(converter, val): ...
    def py2sql(converter, val): ...

class SQLiteJsonConverter(dbapiprovider.JsonConverter):
    json_kwargs: Incomplete

def dumps(items): ...

class SQLiteArrayConverter(dbapiprovider.ArrayConverter):
    array_types: Incomplete
    def dbval2val(converter, dbval, obj=None): ...
    def val2dbval(converter, val, obj=None): ...

class LocalExceptions(localbase):
    exc_info: Incomplete
    keep_traceback: bool
    def __init__(self) -> None: ...

local_exceptions: LocalExceptions

def keep_exception(func): ...

class SQLiteProvider(DBAPIProvider):
    dialect: ClassVar[str]
    local_exceptions: LocalExceptions
    dbapi_module: ClassVar[types.ModuleType]
    dbschema_cls: ClassVar[type[SQLiteSchema]]
    translator_cls: ClassVar[type[SQLiteTranslator]]
    sqlbuilder_cls: ClassVar[type[SQLiteBuilder]]
    array_converter_cls: ClassVar[type[SQLiteArrayConverter]]
    server_version: tuple[int, int, int]
    converter_classes: Incomplete
    def __init__(provider, database, filename, **kwargs) -> None: ...
    def inspect_connection(provider, conn) -> None: ...
    def restore_exception(provider) -> None: ...
    def acquire_lock(provider) -> None: ...
    def release_lock(provider) -> None: ...
    def set_transaction_mode(provider, connection: _Connection, cache) -> None: ...
    def commit(provider, connection: _Connection, cache=None) -> None: ...
    def rollback(provider, connection: _Connection, cache=None) -> None: ...
    def drop(provider, connection: _Connection, cache=None) -> None: ...
    def release(provider, connection: _Connection, cache=None) -> None: ...
    def get_pool(provider, is_shared_memory_db, filename, create_db: bool = False, **kwargs): ...
    def table_exists(provider, connection: _Connection, table_name: str, case_sensitive: bool = True): ...
    def index_exists(provider, connection: _Connection, table_name: str, index_name, case_sensitive: bool = True): ...
    def fk_exists(provider, connection: _Connection, table_name: str, fk_name) -> None: ...  # type: ignore[override]
    def check_json1(provider, connection: _Connection) -> bool: ...

provider_cls = SQLiteProvider

def make_string_function(name, base_func): ...

py_upper: Incomplete
py_lower: Incomplete

@overload
def py_json_unwrap(value: str) -> str | None: ...
@overload
def py_json_unwrap(value: Any) -> None: ...

path_cache: Incomplete
json_path_re: re.Pattern[str]

def py_json_extract(expr, *paths): ...
def py_json_query(expr, path, with_wrapper): ...
def py_json_value(expr, path): ...
def py_json_contains(expr, path, key): ...
def py_json_nonzero(expr, path): ...
def py_json_array_length(expr, path=None): ...
def wrap_array_func(func): ...
def py_array_index(array, index): ...
def py_array_contains(array, item): ...
def py_array_subset(array, items): ...
def py_array_length(array): ...
def py_array_slice(array, start, stop): ...
def py_make_array(*items): ...

@overload
def py_string_slice(s: None, start: str | int | None, end: str | int | None) -> None: ...
@overload
def py_string_slice(s: str, start: str | int | None, end: str | int | None) -> str: ...

class SQLitePool(Pool):
    is_shared_memory_db: bool | None
    filename: StrOrBytesPath
    create_db: bool | None
    kwargs: dict[str, Incomplete]
    if sys.version_info >= (3, 12):
        def __init__(
            pool,
            is_shared_memory_db: bool | None,
            filename: StrOrBytesPath,
            create_db: bool | None,
            *,
            timeout: float = 5.0,
            detect_types: int = 0,
            check_same_thread: bool = True,
            factory: type[_Connection],
            cached_statements: int = 128,
            uri: bool = False,
            autocommit: bool = ...,
        ) -> None: ...
    else:
        def __init__(
            pool,
            is_shared_memory_db: bool | None,
            filename: StrOrBytesPath,
            create_db: bool | None,
            *,
            timeout: float = 5.0,
            detect_types: int = 0,
            check_same_thread: bool = True,
            factory: type[_Connection],
            cached_statements: int = 128,
            uri: bool = False,
        ) -> None: ...

    def disconnect(pool) -> None: ...
    def drop(pool, con: _Connection) -> None: ...
