from typing import Dict, Any, Optional, Union, List, Callable
import pandas as pd
from sqlalchemy import Engine
from sqlalchemy.engine import Engine as SQLAlchemyEngine
import redis

class DatabaseError(Exception): ...
class TableNotFoundError(DatabaseError): ...
class ColumnNotFoundError(DatabaseError): ...
class InvalidOperationError(DatabaseError): ...

class DatabaseManager:
    _connection_string: str
    _table_name: Optional[str]
    _data: Optional[pd.DataFrame]
    _message: Optional[str]
    _channel: Optional[str]
    _pubsub: Optional[redis.client.PubSub]
    _subscriber_thread: Optional[threading.Thread]
    _close_flag: threading.Event
    _close_message: Optional[str]
    _message_history: Dict[str, List[str]]
    _base: str
    _redis_client: Optional[redis.Redis]
    _engine: Optional[SQLAlchemyEngine]

    def __init__(self, connection_string: str) -> None: ...
    def use_table(self, table_name: str) -> 'DatabaseManager': ...
    def message_handler(self, channel: str, message: str) -> None: ...
    def _message_handler_wrapper(self, user_handler: Optional[Callable[[str, str], None]], exiton: str) -> Callable[[dict], None]: ...
    def sub_and_store(self, channel: str, handler: Optional[Callable[[str, str], None]] = None, exiton: str = "") -> 'DatabaseManager': ...
    def get_stored_messages(self, channel: str) -> List[str]: ...
    def clear_stored_messages(self, channel: Optional[str] = None) -> 'DatabaseManager': ...
    def sub(self, channel: str, handler: Optional[Callable[[str, str], None]] = None, exiton: str = "") -> 'DatabaseManager': ...
    def _message_handler_loop(self) -> None: ...
    def pubsub(self, pub_message: str, pub_channel: str, sub_channel: str, handler: Optional[Callable[[str, str], None]] = None, exiton: str = "CLOSE", wait: Optional[int] = None) -> 'DatabaseManager': ...
    def pub(self, message: str, channel: str) -> 'DatabaseManager': ...
    def unsub(self, channel: Optional[str] = None) -> 'DatabaseManager': ...
    def results(self) -> Any: ...
    def read(self) -> 'DatabaseManager': ...
    def dedup(self, subset: Optional[List[str]] = None, keep: str = 'first') -> 'DatabaseManager': ...
    def write(self, data: Optional[pd.DataFrame] = None) -> 'DatabaseManager': ...
    def create(self, data: pd.DataFrame) -> 'DatabaseManager': ...
    def delete_table(self) -> 'DatabaseManager': ...
    def delete_column(self, column_name: str) -> 'DatabaseManager': ...
    def delete_row(self, row_identifier: Dict[str, Any]) -> 'DatabaseManager': ...
    def search(self, conditions: Union[Dict[str, Any], str], limit: Optional[int] = None, case_sensitive: bool = False) -> 'DatabaseManager': ...
    def backup(self, file_path: str, columns: Optional[List[str]] = None) -> 'DatabaseManager': ...
    def restore(self, file_path: str, mode: str = 'replace') -> 'DatabaseManager': ...
    def get_data(self) -> Optional[pd.DataFrame]: ...
    def execute_query(self, query: str, params: Optional[Dict[str, Any]] = None) -> 'DatabaseManager': ...
    def __str__(self) -> str: ...
