import io
import logging
import re
import socket
from _typeshed import ReadableBuffer, Unused
from collections.abc import Callable
from typing import Any, Final, Protocol, type_check_only
from typing_extensions import Self

from gunicorn.config import Config
from gunicorn.http import Request

from .._types import _AddressType, _EnvironType, _HeadersType, _StatusType

BLKSIZE: Final = 0x3FFFFFFF
HEADER_VALUE_RE: Final[re.Pattern[str]]
log: logging.Logger

@type_check_only
class _FileLikeProtocol(Protocol):
    def read(self, size: int, /) -> bytes: ...
    def seek(self, offset: int, /) -> object: ...

    # optional fields:
    # def close(self) -> None: ...
    # def fileno(self) -> int: ...

class FileWrapper:
    filelike: io.IOBase
    blksize: int
    close: Callable[[], None] | None

    def __init__(self, filelike: _FileLikeProtocol, blksize: int = 8192) -> None: ...
    def __getitem__(self, key: Unused) -> bytes: ...
    def __iter__(self) -> Self: ...
    def __next__(self) -> bytes: ...

class WSGIErrorsWrapper(io.RawIOBase):
    streams: list[io.TextIOBase]

    def __init__(self, cfg: Config) -> None: ...
    def write(self, data: ReadableBuffer) -> None: ...

def base_environ(cfg: Config) -> _EnvironType: ...
def default_environ(req: Request, sock: socket.socket, cfg: Config) -> _EnvironType: ...
def proxy_environ(req: Request) -> _EnvironType: ...
def create(
    req: Request, sock: socket.socket, client: _AddressType, server: _AddressType, cfg: Config
) -> tuple[Response, _EnvironType]: ...

class Response:
    req: Request
    sock: socket.socket
    version: str
    status: str | None
    chunked: bool
    must_close: bool
    headers: _HeadersType
    headers_sent: bool
    response_length: int | None
    sent: int
    upgrade: bool
    cfg: Config
    status_code: int | None

    def __init__(self, req: Request, sock: socket.socket, cfg: Config) -> None: ...
    def force_close(self) -> None: ...
    def should_close(self) -> bool: ...
    def start_response(
        self, status: _StatusType, headers: _HeadersType, exc_info: tuple[type, BaseException, Any] | None = None
    ) -> Callable[[bytes], None]: ...
    def process_headers(self, headers: _HeadersType) -> None: ...
    def is_chunked(self) -> bool: ...
    def default_headers(self) -> list[str]: ...
    def send_headers(self) -> None: ...
    def write(self, arg: bytes) -> None: ...
    def can_sendfile(self) -> bool: ...
    def sendfile(self, respiter: FileWrapper) -> bool: ...
    def write_file(self, respiter: FileWrapper) -> None: ...
    def close(self) -> None: ...
