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

import pytz
from pytz import BaseTzInfo
from typing_extensions import 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]: ...
