from datetime import datetime, timezone
from functools import lru_cache
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

from app.settings import APP_TIMEZONE


@lru_cache(maxsize=1)
def obter_timezone_app():
    for nome_timezone in (APP_TIMEZONE, "America/Sao_Paulo"):
        try:
            return ZoneInfo(nome_timezone)
        except ZoneInfoNotFoundError:
            continue

    return timezone.utc


def agora_local() -> datetime:
    return datetime.now(obter_timezone_app())


def agora_local_banco() -> datetime:
    """Horário local compatível com colunas MySQL ``DATETIME``."""
    return agora_local().replace(tzinfo=None)


def horario_do_envio(valor: str | datetime | None) -> datetime:
    """Converte o instante enviado pelo navegador para o fuso da aplicação."""
    if isinstance(valor, datetime):
        data_hora = valor
    else:
        try:
            data_hora = datetime.fromisoformat(str(valor or "").strip().replace("Z", "+00:00"))
        except ValueError:
            return agora_local_banco()
    if data_hora.tzinfo is None:
        return data_hora
    return data_hora.astimezone(obter_timezone_app()).replace(tzinfo=None)


def fromtimestamp_local(timestamp: float) -> datetime:
    return datetime.fromtimestamp(timestamp, tz=obter_timezone_app())
