import datetime
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
from http.cookies import SimpleCookie
from io import BytesIO
from json import JSONEncoder
from typing import Any, Literal, NoReturn, TypeVar, overload, type_check_only

from django.utils.datastructures import CaseInsensitiveMapping, _PropertyDescriptor
from django.utils.functional import _StrOrPromise, cached_property

class BadHeaderError(ValueError): ...

_Z = TypeVar("_Z")

class ResponseHeaders(CaseInsensitiveMapping[str]):
    def __init__(self, data: dict[str, str]) -> None: ...
    def _convert_to_charset(self, value: bytes | str | int, charset: str, mime_encode: bool = ...) -> str: ...
    def __delitem__(self, key: str) -> None: ...
    def __setitem__(self, key: str, value: str | bytes | int) -> None: ...
    def pop(self, key: str, default: _Z = ...) -> _Z | tuple[str, str]: ...
    def setdefault(self, key: str, value: str | bytes | int) -> None: ...

class HttpResponseBase:
    status_code: int
    streaming: bool
    cookies: SimpleCookie
    closed: bool
    headers: ResponseHeaders
    def __init__(
        self,
        content_type: str | None = ...,
        status: int | None = ...,
        reason: str | None = ...,
        charset: str | None = ...,
        headers: dict[str, str] | None = ...,
    ) -> None: ...
    @property
    def reason_phrase(self) -> str: ...
    @reason_phrase.setter
    def reason_phrase(self, value: str) -> None: ...
    @property
    def charset(self) -> str: ...
    @charset.setter
    def charset(self, value: str) -> None: ...
    def serialize_headers(self) -> bytes: ...
    __bytes__ = serialize_headers
    def __setitem__(self, header: str, value: str | bytes | int) -> None: ...
    def __delitem__(self, header: str) -> None: ...
    def __getitem__(self, header: str) -> str: ...
    def has_header(self, header: str) -> bool: ...
    def __contains__(self, header: str) -> bool: ...
    def items(self) -> Iterable[tuple[str, str]]: ...
    @overload
    def get(self, header: str, alternate: str) -> str: ...
    @overload
    def get(self, header: str, alternate: None = None) -> str | None: ...
    def set_cookie(
        self,
        key: str,
        value: str = ...,
        max_age: int | datetime.timedelta | None = ...,
        expires: str | datetime.datetime | None = ...,
        path: str = ...,
        domain: str | None = ...,
        secure: bool = ...,
        httponly: bool = ...,
        samesite: Literal["Lax", "Strict", "None", False] | None = ...,
    ) -> None: ...
    def setdefault(self, key: str, value: str) -> None: ...
    def set_signed_cookie(self, key: str, value: str, salt: str = ..., **kwargs: Any) -> None: ...
    def delete_cookie(
        self,
        key: str,
        path: str = ...,
        domain: str | None = ...,
        samesite: Literal["Lax", "Strict", "None", False] | None = ...,
    ) -> None: ...
    def make_bytes(self, value: object) -> bytes: ...
    def close(self) -> None: ...
    def write(self, content: str | bytes) -> None: ...
    def flush(self) -> None: ...
    def tell(self) -> int: ...
    def readable(self) -> bool: ...
    def seekable(self) -> bool: ...
    def writable(self) -> bool: ...
    def writelines(self, lines: Iterable[object]) -> None: ...

    # Fake methods that are implemented by all subclasses
    @type_check_only
    def __iter__(self) -> Iterator[bytes]: ...
    @type_check_only
    def getvalue(self) -> bytes: ...

class HttpResponse(HttpResponseBase, Iterable[bytes]):
    content = _PropertyDescriptor[object, bytes]()
    csrf_cookie_set: bool
    sameorigin: bool
    test_server_port: str
    test_was_secure_request: bool
    xframe_options_exempt: bool
    def __init__(self, content: object = ..., *args: Any, **kwargs: Any) -> None: ...
    def serialize(self) -> bytes: ...
    __bytes__ = serialize
    def __iter__(self) -> Iterator[bytes]: ...
    def getvalue(self) -> bytes: ...
    @cached_property
    def text(self) -> str: ...

class StreamingHttpResponse(HttpResponseBase, Iterable[bytes], AsyncIterable[bytes]):
    is_async: bool
    streaming_content = _PropertyDescriptor[
        Iterable[object] | AsyncIterable[object], Iterator[bytes] | AsyncIterator[bytes]
    ]()
    def __init__(
        self, streaming_content: Iterable[object] | AsyncIterable[object] = ..., *args: Any, **kwargs: Any
    ) -> None: ...
    def __iter__(self) -> Iterator[bytes]: ...
    def __aiter__(self) -> AsyncIterator[bytes]: ...
    def getvalue(self) -> bytes: ...
    @property
    def content(self) -> NoReturn: ...
    @property
    def text(self) -> NoReturn: ...

class FileResponse(StreamingHttpResponse):
    file_to_stream: BytesIO | None
    block_size: int
    as_attachment: bool
    filename: str
    def __init__(self, *args: Any, as_attachment: bool = ..., filename: str = ..., **kwargs: Any) -> None: ...
    def set_headers(self, filelike: BytesIO) -> None: ...

class HttpResponseRedirectBase(HttpResponse):
    allowed_schemes: list[str]
    def __init__(
        self, redirect_to: _StrOrPromise, preserve_request: bool = False, *args: Any, **kwargs: Any
    ) -> None: ...
    @property
    def url(self) -> str: ...

class HttpResponseRedirect(HttpResponseRedirectBase):
    status_code_preserve_request: int

class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
    status_code_preserve_request: int

class HttpResponseNotModified(HttpResponse):
    def __init__(self, *args: Any, **kwargs: Any) -> None: ...

class HttpResponseBadRequest(HttpResponse): ...
class HttpResponseNotFound(HttpResponse): ...
class HttpResponseForbidden(HttpResponse): ...

class HttpResponseNotAllowed(HttpResponse):
    def __init__(self, permitted_methods: Iterable[str], *args: Any, **kwargs: Any) -> None: ...

class HttpResponseGone(HttpResponse): ...
class HttpResponseServerError(HttpResponse): ...
class Http404(Exception): ...

class JsonResponse(HttpResponse):
    def __init__(
        self,
        data: Any,
        encoder: type[JSONEncoder] = ...,
        safe: bool = ...,
        json_dumps_params: dict[str, Any] | None = ...,
        **kwargs: Any,
    ) -> None: ...
