"""
Core DateTime Utilities

Low-level datetime operations for the bakery system.
All functions use Python's built-in zoneinfo for timezone handling.
"""

from datetime import datetime, timezone
from typing import Optional
from zoneinfo import ZoneInfo

from .constants import DEFAULT_TIMEZONE, ISO_FORMAT


def utc_now() -> datetime:
    """
    Get current datetime in UTC with timezone awareness.

    Returns:
        Current UTC datetime
    """
    return datetime.now(timezone.utc)


def now_in_timezone(tz: str = DEFAULT_TIMEZONE) -> datetime:
    """
    Get current datetime in specified timezone.

    Args:
        tz: IANA timezone string (e.g., "Europe/Madrid")

    Returns:
        Current datetime in the specified timezone
    """
    return datetime.now(ZoneInfo(tz))


def to_utc(dt: datetime) -> datetime:
    """
    Convert datetime to UTC.

    Args:
        dt: Datetime to convert (if naive, assumes UTC)

    Returns:
        Datetime in UTC timezone
    """
    if dt.tzinfo is None:
        return dt.replace(tzinfo=timezone.utc)
    return dt.astimezone(timezone.utc)


def to_timezone(dt: datetime, tz: str) -> datetime:
    """
    Convert datetime to specified timezone.

    Args:
        dt: Datetime to convert (if naive, assumes UTC)
        tz: Target IANA timezone string

    Returns:
        Datetime in target timezone
    """
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    return dt.astimezone(ZoneInfo(tz))


def ensure_aware(dt: datetime, default_tz: str = "UTC") -> datetime:
    """
    Ensure a datetime is timezone-aware.

    Args:
        dt: Datetime to check
        default_tz: Timezone to apply if datetime is naive (default: UTC)

    Returns:
        Timezone-aware datetime
    """
    if dt.tzinfo is None:
        tz = ZoneInfo(default_tz)
        return dt.replace(tzinfo=tz)
    return dt


def ensure_naive(dt: datetime) -> datetime:
    """
    Remove timezone information from a datetime.

    Args:
        dt: Datetime to process

    Returns:
        Timezone-naive datetime
    """
    if dt.tzinfo is not None:
        return dt.replace(tzinfo=None)
    return dt


def parse_iso(dt_str: str) -> datetime:
    """
    Parse ISO format datetime string.

    Args:
        dt_str: ISO format datetime string

    Returns:
        Parsed datetime (timezone-aware if timezone info present)
    """
    return datetime.fromisoformat(dt_str)


def format_iso(dt: datetime) -> str:
    """
    Format datetime as ISO string.

    Args:
        dt: Datetime to format

    Returns:
        ISO format string
    """
    return dt.isoformat()


def format_custom(dt: datetime, format_str: str = ISO_FORMAT) -> str:
    """
    Format datetime with custom format string.

    Args:
        dt: Datetime to format
        format_str: strftime format string

    Returns:
        Formatted datetime string
    """
    return dt.strftime(format_str)


def is_aware(dt: datetime) -> bool:
    """
    Check if datetime is timezone-aware.

    Args:
        dt: Datetime to check

    Returns:
        True if timezone-aware, False otherwise
    """
    return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None


def validate_timezone(tz: str) -> bool:
    """
    Validate if timezone string is valid.

    Args:
        tz: IANA timezone string to validate

    Returns:
        True if valid, False otherwise
    """
    try:
        ZoneInfo(tz)
        return True
    except Exception:
        return False
