"""Timezone utilities for consistent local time handling."""

from __future__ import annotations

from datetime import UTC, datetime
from functools import lru_cache
from zoneinfo import ZoneInfo

import structlog

from app.config import settings


logger = structlog.get_logger(__name__)


@lru_cache(maxsize=1)
def get_local_timezone() -> ZoneInfo:
    """Return the configured local timezone.

    Falls back to UTC if the configured timezone cannot be loaded. The
    fallback is logged once and cached for subsequent calls.
    """

    tz_name = settings.TIMEZONE

    try:
        return ZoneInfo(tz_name)
    except Exception as exc:  # pragma: no cover - defensive branch
        logger.warning("⚠️ Не удалось загрузить временную зону '': . Используем UTC.", tz_name=tz_name, exc=exc)
        return ZoneInfo('UTC')


def panel_datetime_to_utc(dt: datetime) -> datetime:
    """Convert a panel datetime to aware UTC.

    Panel API returns local time with a misleading UTC offset (+00:00 / Z).
    This strips the offset, interprets the raw value as panel-local time,
    then converts to aware UTC for database storage.
    """
    naive = dt
    localized = naive.replace(tzinfo=get_local_timezone())
    return localized.astimezone(ZoneInfo('UTC'))


def to_local_datetime(dt: datetime | None) -> datetime | None:
    """Convert a datetime value to the configured local timezone."""

    if dt is None:
        return None

    aware_dt = dt if dt.tzinfo is not None else dt.replace(tzinfo=UTC)
    return aware_dt.astimezone(get_local_timezone())


def format_local_datetime(
    dt: datetime | None,
    fmt: str = '%Y-%m-%d %H:%M:%S %Z',
    na_placeholder: str = 'N/A',
) -> str:
    """Format a datetime value in the configured local timezone."""

    localized = to_local_datetime(dt)
    if localized is None:
        return na_placeholder
    return localized.strftime(fmt)
