from contextlib import ContextDecorator
from datetime import date, datetime, time, timedelta, timezone, tzinfo
from types import TracebackType
from typing import Any, overload

import pytz
from pytz import BaseTzInfo
from typing_extensions import Literal, TypeAlias, TypeGuard

_PytzTzInfoT: TypeAlias = pytz.tzinfo.BaseTzInfo | pytz._FixedOffset

_TzInfoT: TypeAlias = _PytzTzInfoT | tzinfo

utc: Any

def get_fixed_timezone(offset: timedelta | int) -> timezone: ...
def get_default_timezone() -> BaseTzInfo: ...
def get_default_timezone_name() -> str: ...

# Strictly speaking, it is possible to activate() a non-pytz timezone,
# in which case BaseTzInfo is incorrect. However, this is unlikely,
# so we use it anyway, to keep things ergonomic for most users.
def get_current_timezone() -> BaseTzInfo: ...
def get_current_timezone_name() -> str: ...
def activate(timezone: _TzInfoT | str) -> None: ...
def deactivate() -> None: ...

class override(ContextDecorator):
    timezone: str | _TzInfoT | None
    old_timezone: _TzInfoT | None
    def __init__(self, timezone: str | _TzInfoT | None) -> None: ...
    def __enter__(self) -> None: ...
    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_value: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None: ...

def localtime(value: datetime | None = ..., timezone: _TzInfoT | None = ...) -> datetime: ...
def localdate(value: datetime | None = ..., timezone: _TzInfoT | None = ...) -> date: ...
def now() -> datetime: ...
@overload
def is_aware(value: time) -> Literal[False]: ...
@overload
def is_aware(value: datetime) -> bool: ...
@overload
def is_naive(value: time) -> Literal[True]: ...
@overload
def is_naive(value: datetime) -> bool: ...
def make_aware(value: datetime, timezone: _TzInfoT | None = ..., is_dst: bool | None = ...) -> datetime: ...
def make_naive(value: datetime, timezone: _TzInfoT | None = ...) -> datetime: ...
def _is_pytz_zone(tz: _TzInfoT) -> TypeGuard[_PytzTzInfoT]: ...
