"""Implements ThreadPoolExecutor."""

import queue
import sys
from collections.abc import Callable, Iterable, Mapping, Set as AbstractSet
from threading import Lock, Semaphore, Thread
from types import GenericAlias
from typing import Any, Generic, Protocol, TypeVar, overload, type_check_only
from typing_extensions import Self, TypeAlias, TypeVarTuple, Unpack
from weakref import ref

from ._base import BrokenExecutor, Executor, Future

_Ts = TypeVarTuple("_Ts")

_threads_queues: Mapping[Any, Any]
_shutdown: bool
_global_shutdown_lock: Lock

def _python_exit() -> None: ...

_S = TypeVar("_S")

_Task: TypeAlias = tuple[Callable[..., Any], tuple[Any, ...], dict[str, Any]]

_C = TypeVar("_C", bound=Callable[..., object])
_KT = TypeVar("_KT", bound=str)
_VT = TypeVar("_VT")

@type_check_only
class _ResolveTaskFunc(Protocol):
    def __call__(
        self, func: _C, args: tuple[Unpack[_Ts]], kwargs: dict[_KT, _VT]
    ) -> tuple[_C, tuple[Unpack[_Ts]], dict[_KT, _VT]]: ...

if sys.version_info >= (3, 14):
    class WorkerContext:
        @overload
        @classmethod
        def prepare(
            cls, initializer: Callable[[Unpack[_Ts]], object], initargs: tuple[Unpack[_Ts]]
        ) -> tuple[Callable[[], Self], _ResolveTaskFunc]: ...
        @overload
        @classmethod
        def prepare(
            cls, initializer: Callable[[], object], initargs: tuple[()]
        ) -> tuple[Callable[[], Self], _ResolveTaskFunc]: ...
        @overload
        def __init__(self, initializer: Callable[[Unpack[_Ts]], object], initargs: tuple[Unpack[_Ts]]) -> None: ...
        @overload
        def __init__(self, initializer: Callable[[], object], initargs: tuple[()]) -> None: ...
        def initialize(self) -> None: ...
        def finalize(self) -> None: ...
        def run(self, task: _Task) -> None: ...

if sys.version_info >= (3, 14):
    class _WorkItem(Generic[_S]):
        future: Future[Any]
        task: _Task
        def __init__(self, future: Future[Any], task: _Task) -> None: ...
        def run(self, ctx: WorkerContext) -> None: ...
        def __class_getitem__(cls, item: Any, /) -> GenericAlias:
            """Represent a PEP 585 generic type

            E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
            """

    def _worker(executor_reference: ref[Any], ctx: WorkerContext, work_queue: queue.SimpleQueue[Any]) -> None: ...

else:
    class _WorkItem(Generic[_S]):
        future: Future[_S]
        fn: Callable[..., _S]
        args: Iterable[Any]
        kwargs: Mapping[str, Any]
        def __init__(self, future: Future[_S], fn: Callable[..., _S], args: Iterable[Any], kwargs: Mapping[str, Any]) -> None: ...
        def run(self) -> None: ...
        def __class_getitem__(cls, item: Any, /) -> GenericAlias:
            """Represent a PEP 585 generic type

            E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
            """

    def _worker(
        executor_reference: ref[Any],
        work_queue: queue.SimpleQueue[Any],
        initializer: Callable[[Unpack[_Ts]], object],
        initargs: tuple[Unpack[_Ts]],
    ) -> None: ...

class BrokenThreadPool(BrokenExecutor):
    """
    Raised when a worker thread in a ThreadPoolExecutor failed initializing.
    """

class ThreadPoolExecutor(Executor):
    if sys.version_info >= (3, 14):
        BROKEN: type[BrokenThreadPool]

    _max_workers: int
    _idle_semaphore: Semaphore
    _threads: AbstractSet[Thread]
    _broken: bool
    _shutdown: bool
    _shutdown_lock: Lock
    _thread_name_prefix: str | None
    if sys.version_info >= (3, 14):
        _create_worker_context: Callable[[], WorkerContext]
        _resolve_work_item_task: _ResolveTaskFunc
    else:
        _initializer: Callable[..., None] | None
        _initargs: tuple[Any, ...]
    _work_queue: queue.SimpleQueue[_WorkItem[Any]]

    if sys.version_info >= (3, 14):
        @overload
        @classmethod
        def prepare_context(
            cls, initializer: Callable[[], object], initargs: tuple[()]
        ) -> tuple[Callable[[], WorkerContext], _ResolveTaskFunc]: ...
        @overload
        @classmethod
        def prepare_context(
            cls, initializer: Callable[[Unpack[_Ts]], object], initargs: tuple[Unpack[_Ts]]
        ) -> tuple[Callable[[], WorkerContext], _ResolveTaskFunc]: ...

    @overload
    def __init__(
        self,
        max_workers: int | None = None,
        thread_name_prefix: str = "",
        initializer: Callable[[], object] | None = None,
        initargs: tuple[()] = (),
    ) -> None:
        """Initializes a new ThreadPoolExecutor instance.

        Args:
            max_workers: The maximum number of threads that can be used to
                execute the given calls.
            thread_name_prefix: An optional name prefix to give our threads.
            initializer: A callable used to initialize worker threads.
            initargs: A tuple of arguments to pass to the initializer.
            ctxkwargs: Additional arguments to cls.prepare_context().
        """

    @overload
    def __init__(
        self,
        max_workers: int | None = None,
        thread_name_prefix: str = "",
        *,
        initializer: Callable[[Unpack[_Ts]], object],
        initargs: tuple[Unpack[_Ts]],
    ) -> None: ...
    @overload
    def __init__(
        self,
        max_workers: int | None,
        thread_name_prefix: str,
        initializer: Callable[[Unpack[_Ts]], object],
        initargs: tuple[Unpack[_Ts]],
    ) -> None: ...
    def _adjust_thread_count(self) -> None: ...
    def _initializer_failed(self) -> None: ...
