"""
Timezone Operations

Timezone metadata and conversion utilities.
"""

from datetime import datetime, date, time
from zoneinfo import ZoneInfo
from typing import Optional
import structlog

from .constants import DEFAULT_TIMEZONE, SUPPORTED_TIMEZONES

logger = structlog.get_logger()


def get_timezone_info(tz: str) -> ZoneInfo:
    """
    Get ZoneInfo object for timezone.

    Args:
        tz: IANA timezone string

    Returns:
        ZoneInfo object

    Raises:
        ZoneInfoNotFoundError: If timezone is invalid
    """
    return ZoneInfo(tz)


def get_utc_offset_hours(tz: str) -> float:
    """
    Get current UTC offset for timezone in hours.

    Args:
        tz: IANA timezone string

    Returns:
        UTC offset in hours (e.g., +2.0 for CEST)
    """
    try:
        zone = ZoneInfo(tz)
        now = datetime.now(zone)
        offset_seconds = now.utcoffset().total_seconds()
        return offset_seconds / 3600
    except Exception as e:
        logger.warning(f"Could not get offset for {tz}", error=str(e))
        return 0.0


def list_supported_timezones() -> list[str]:
    """
    Get list of supported timezones.

    Returns:
        List of IANA timezone strings
    """
    return sorted(SUPPORTED_TIMEZONES)


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

    Args:
        tz: IANA timezone string

    Returns:
        Current date in the specified timezone
    """
    try:
        zone = ZoneInfo(tz)
        return datetime.now(zone).date()
    except Exception as e:
        logger.warning(f"Invalid timezone {tz}, using default", error=str(e))
        return datetime.now(ZoneInfo(DEFAULT_TIMEZONE)).date()


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

    Args:
        tz: IANA timezone string

    Returns:
        Current datetime in the specified timezone
    """
    try:
        zone = ZoneInfo(tz)
        return datetime.now(zone)
    except Exception as e:
        logger.warning(f"Invalid timezone {tz}, using default", error=str(e))
        return datetime.now(ZoneInfo(DEFAULT_TIMEZONE))


def combine_date_time_in_tz(
    target_date: date,
    target_time: time,
    tz: str = DEFAULT_TIMEZONE
) -> datetime:
    """
    Combine date and time in specified timezone.

    Args:
        target_date: Date component
        target_time: Time component
        tz: IANA timezone string

    Returns:
        Datetime combining date and time in specified timezone
    """
    try:
        zone = ZoneInfo(tz)
        return datetime.combine(target_date, target_time, tzinfo=zone)
    except Exception as e:
        logger.warning(f"Invalid timezone {tz}, using default", error=str(e))
        zone = ZoneInfo(DEFAULT_TIMEZONE)
        return datetime.combine(target_date, target_time, tzinfo=zone)


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

    Args:
        dt: Datetime to convert (must be timezone-aware)

    Returns:
        Datetime in UTC timezone
    """
    if dt.tzinfo is None:
        logger.warning("Converting naive datetime to UTC, assuming UTC")
        return dt.replace(tzinfo=ZoneInfo("UTC"))
    return dt.astimezone(ZoneInfo("UTC"))


def convert_from_utc(dt: datetime, target_timezone: str) -> datetime:
    """
    Convert UTC datetime to target timezone.

    Args:
        dt: UTC datetime
        target_timezone: Target IANA timezone string

    Returns:
        Datetime in target timezone
    """
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=ZoneInfo("UTC"))

    try:
        zone = ZoneInfo(target_timezone)
        return dt.astimezone(zone)
    except Exception as e:
        logger.warning(f"Invalid timezone {target_timezone}, using default", error=str(e))
        zone = ZoneInfo(DEFAULT_TIMEZONE)
        return dt.astimezone(zone)
