import re
from datetime import datetime
from zoneinfo import ZoneInfo

from app.config import settings


def get_tz() -> ZoneInfo:
    return ZoneInfo(settings.timezone)


def now() -> datetime:
    """Devuelve la fecha/hora actual en la zona horaria configurada (aware)."""
    return datetime.now(get_tz())


def parse_iso(value) -> datetime | None:
    """Convierte una fecha ISO-8601 (string de Alfresco o datetime) a datetime.
    Soporta sufijos `Z` y offsets sin dos puntos (`+0000`)."""
    if value is None:
        return None
    if isinstance(value, datetime):
        return value
    s = str(value).strip()
    if not s:
        return None
    if s.endswith("Z"):
        s = s[:-1] + "+00:00"
    s = re.sub(r"([+-]\d{2})(\d{2})$", r"\1:\2", s)
    try:
        return datetime.fromisoformat(s)
    except Exception:
        return None


def to_local(dt) -> datetime | None:
    """Convierte un datetime a la zona horaria configurada.
    Los datetimes naive se asumen en hora local (la BD almacena hora local)."""
    if dt is None:
        return None
    if isinstance(dt, str):
        dt = parse_iso(dt)
        if dt is None:
            return None
    if dt.tzinfo is None:
        return dt.replace(tzinfo=get_tz())
    return dt.astimezone(get_tz())


def iso(dt) -> str | None:
    """Serializa un datetime a ISO-8601 en la zona horaria configurada (incluye offset)."""
    local = to_local(dt)
    return local.isoformat() if local is not None else None


def strftime(dt, fmt: str) -> str:
    """Formatea un datetime en la zona horaria configurada."""
    return to_local(dt).strftime(fmt)
