"""Protocols for query execution mixins."""

from __future__ import annotations

from collections.abc import Awaitable
from typing import TYPE_CHECKING, Any, Protocol

if TYPE_CHECKING:
    from textual.timer import Timer
    from textual.worker import Worker

    from sqlit.domains.query.editing.deletion import EditResult
    from sqlit.shared.ui.spinner import Spinner
    from sqlit.shared.ui.widgets import SqlitDataTable


class QueryStateProtocol(Protocol):
    _query_worker: Worker[Any] | None
    query_executing: bool
    _query_start_time: float
    _spinner_index: int
    _spinner_timer: Timer | None
    _query_handle: Any | None
    _query_service: Any | None
    _query_service_db_type: str | None
    _cancellable_query: Any | None
    _query_spinner: Spinner | None
    _process_worker_client: Any | None
    _process_worker_client_error: str | None
    _process_worker_last_used: float | None
    _process_worker_idle_timer: Timer | None
    _query_cursor_cache: dict[str, tuple[int, int]] | None
    _undo_history: Any | None
    _transaction_executor: Any | None
    _transaction_executor_config: Any | None
    _results_render_worker: Worker[Any] | None
    _results_render_token: int


class QueryActionsProtocol(Protocol):
    _history_store: Any | None

    def action_execute_query(self) -> None:
        ...

    def action_execute_query_atomic(self) -> None:
        ...

    def action_execute_single_statement(self) -> None:
        ...

    def _get_history_store(self) -> Any:
        ...

    def _get_query_service(self, provider: Any) -> Any:
        ...

    def _execute_query_common(self, keep_insert_mode: bool) -> None:
        ...

    def _start_query_spinner(self) -> None:
        ...

    def _run_query_async(self, query: str, keep_insert_mode: bool) -> Awaitable[None]:
        ...

    def _animate_spinner(self) -> None:
        ...

    def _display_query_error(self, error_message: str) -> None:
        ...

    def _stop_query_spinner(self) -> None:
        ...

    def _display_query_results(
        self, columns: list[str], rows: list[tuple[Any, ...]], row_count: int, truncated: bool, elapsed_ms: float
    ) -> Awaitable[None]:
        ...

    def _display_non_query_result(self, affected: int, elapsed_ms: float) -> None:
        ...

    def _restore_insert_mode(self) -> None:
        ...

    def _handle_history_result(self, result: Any) -> None:
        ...

    def _delete_history_entry(self, timestamp: str) -> None:
        ...

    def action_show_history(self) -> None:
        ...

    def action_copy_query(self) -> None:
        ...

    def action_copy_cell(self) -> None:
        ...

    def _toggle_star(self, query: str) -> None:
        ...

    def _clear_query_target_database(self) -> None:
        ...

    def _clear_leader_pending(self) -> None:
        ...

    def _delete_with_motion(self, motion_key: str, char: str | None = None) -> None:
        ...

    def _delete_with_text_object(self, obj_char: str, around: bool) -> None:
        ...

    def _show_char_pending_menu(self, motion: str) -> None:
        ...

    def _show_text_object_menu(self, mode: str) -> None:
        ...

    def _get_clipboard_text(self, prefer_internal: bool = False) -> str:
        ...

    def _paste_text(self, clipboard: str) -> None:
        ...

    def _get_undo_history(self) -> Any:
        ...

    def _push_undo_state(self) -> None:
        ...

    def _apply_edit_result(self, result: EditResult) -> None:
        ...

    def _has_selection(self) -> bool:
        ...

    def _ordered_selection(self, selection: Any) -> tuple[tuple[int, int], tuple[int, int]]:
        ...

    def _selection_range(self, start: tuple[int, int], end: tuple[int, int]) -> Any:
        ...

    def _flash_yank_range(self, start_row: int, start_col: int, end_row: int, end_col: int) -> None:
        ...

    def _yank_selection(self) -> None:
        ...

    def _show_yank_char_pending_menu(self, motion: str) -> None:
        ...

    def _show_yank_text_object_menu(self, mode: str) -> None:
        ...

    def _yank_with_motion(self, motion_key: str, char: str | None = None) -> None:
        ...

    def _yank_with_text_object(self, obj_char: str, around: bool) -> None:
        ...

    def _change_selection(self) -> None:
        ...

    def _enter_insert_mode(self) -> None:
        ...

    def _show_change_char_pending_menu(self, motion: str) -> None:
        ...

    def _show_change_text_object_menu(self, mode: str) -> None:
        ...

    def _change_with_motion(self, motion_key: str, char: str | None = None) -> None:
        ...

    def _change_with_text_object(self, obj_char: str, around: bool) -> None:
        ...

    def _extend_selection(self, new_row: int, new_col: int) -> None:
        ...

    def _replace_results_table_with_data(
        self,
        columns: list[str],
        rows: list[tuple],
        *,
        escape: bool,
    ) -> None:
        ...

    def _build_results_table(
        self,
        columns: list[str],
        rows: list[tuple],
        *,
        escape: bool,
    ) -> SqlitDataTable:
        ...

    def _run_query_atomic_async(self, query: str) -> Awaitable[None]:
        ...

    def _reset_transaction_executor(self) -> None:
        ...

    def _get_transaction_executor(self, config: Any, provider: Any) -> Any:
        ...

    def _display_multi_statement_results(self, multi_result: Any, elapsed_ms: float) -> None:
        ...

    def _get_stacked_results_container(self) -> Any:
        ...

    def _show_stacked_results_mode(self) -> None:
        ...

    def action_enter_insert_mode(self) -> None:
        ...

    def _get_and_clear_count(self) -> int | None:
        ...

    def _clear_count_buffer(self) -> None:
        ...


class QueryProtocol(QueryStateProtocol, QueryActionsProtocol, Protocol):
    """Composite protocol for query-related mixins."""

    pass
