"""
Timezone utilities for venue-aware date/time handling
"""

import os
import time
import logging
from datetime import datetime, timezone, timedelta
from typing import Optional

try:
    import pytz
    HAS_PYTZ = True
except ImportError:
    HAS_PYTZ = False
    logging.warning("pytz not available, timezone detection may be limited")

logger = logging.getLogger(__name__)


def get_system_timezone() -> str:
    """Auto-detect system's local timezone"""
    try:
        # Method 1: Use pytz for comprehensive detection
        if HAS_PYTZ:
            local_tz = pytz.timezone('UTC').localize(datetime.utcnow()).astimezone().tzinfo
            # Find the IANA name
            for tz_name in pytz.all_timezones:
                try:
                    if pytz.timezone(tz_name) == local_tz:
                        return tz_name
                except:
                    continue

        # Method 2: Use dateutil
        try:
            from dateutil import tz
            local_tz = tz.tzlocal()
            now = datetime.now(local_tz)
            # Try to match with pytz names
            if HAS_PYTZ:
                for tz_name in pytz.all_timezones:
                    try:
                        if pytz.timezone(tz_name) == local_tz:
                            return tz_name
                    except:
                        continue
            # Fallback to offset representation
            offset_seconds = local_tz.utcoffset(now).total_seconds()
            offset_hours = offset_seconds / 3600
            return f"UTC{offset_hours:+.0f}".replace('.0', '')
        except ImportError:
            pass

        # Method 3: Basic system timezone detection
        if hasattr(time, 'tzname') and time.tzname:
            tz_name = time.tzname[0]
            # Try to map common abbreviations to IANA names
            tz_mapping = {
                'EST': 'America/New_York',
                'EDT': 'America/New_York',
                'CST': 'America/Chicago',
                'CDT': 'America/Chicago',
                'MST': 'America/Denver',
                'MDT': 'America/Denver',
                'PST': 'America/Los_Angeles',
                'PDT': 'America/Los_Angeles',
                'GMT': 'Europe/London',
                'BST': 'Europe/London',
                'CET': 'Europe/Paris',
                'CEST': 'Europe/Paris',
                'JST': 'Asia/Tokyo',
                'SGT': 'Asia/Singapore',
                'IST': 'Asia/Kolkata',
                'CAT': 'Africa/Johannesburg',
                'SAST': 'Africa/Johannesburg',
                'EAT': 'Africa/Nairobi',
                'WAT': 'Africa/Lagos',
            }
            if tz_name in tz_mapping:
                return tz_mapping[tz_name]
            # If we can't map it, return as-is but log warning
            logger.warning(f"Could not map timezone abbreviation '{tz_name}' to IANA name")
            return tz_name

        # Method 4: Offset-based detection
        offset_seconds = -time.timezone if not time.daylight else -time.altzone
        offset_hours = offset_seconds / 3600
        return f"UTC{offset_hours:+.0f}".replace('.0', '')

    except Exception as e:
        logger.error(f"Failed to detect system timezone: {e}")
        # Fallback to UTC as a safe default
        return 'UTC'


def get_default_venue_timezone() -> str:
    """Get default venue timezone with auto-detection and environment override"""
    # Check environment variable first (for containers/deployments)
    env_tz = os.environ.get('VENUE_TIMEZONE')
    if env_tz:
        if validate_timezone(env_tz):
            logger.info(f"Using venue timezone from environment: {env_tz}")
            return env_tz
        else:
            logger.warning(f"Invalid timezone in VENUE_TIMEZONE: {env_tz}")

    # Auto-detect from system
    detected_tz = get_system_timezone()
    logger.info(f"Auto-detected venue timezone: {detected_tz}")
    return detected_tz


def validate_timezone(tz_name: str) -> bool:
    """Validate timezone name"""
    if not HAS_PYTZ:
        # Basic validation without pytz
        try:
            timezone(timedelta(hours=0))  # Just test if we can create a timezone
            return True
        except:
            return False

    try:
        pytz.timezone(tz_name)
        return True
    except:
        return False


def get_venue_timezone(db_manager) -> timezone:
    """Get configured venue timezone object"""
    venue_tz_str = db_manager.get_config_value('venue_timezone', get_default_venue_timezone())

    if HAS_PYTZ:
        return pytz.timezone(venue_tz_str)
    else:
        # Fallback without pytz - assume UTC offset format
        try:
            if venue_tz_str.startswith('UTC'):
                offset_str = venue_tz_str[3:]  # Remove 'UTC'
                offset_hours = float(offset_str)
                return timezone(timedelta(hours=offset_hours))
            else:
                logger.warning(f"Non-UTC timezone '{venue_tz_str}' specified but pytz not available")
                return timezone.utc
        except:
            logger.error(f"Invalid timezone format: {venue_tz_str}")
            return timezone.utc


def get_today_venue_date(db_manager) -> datetime.date:
    """Get today's date in venue timezone"""
    venue_tz = get_venue_timezone(db_manager)
    if HAS_PYTZ:
        return datetime.now(venue_tz).date()
    else:
        # Without pytz, assume venue_tz is already a timezone object
        return datetime.now(venue_tz).date()


def utc_to_venue_datetime(utc_dt: datetime, db_manager) -> datetime:
    """Convert UTC datetime to venue local time"""
    venue_tz = get_venue_timezone(db_manager)
    if utc_dt.tzinfo is None:
        utc_dt = utc_dt.replace(tzinfo=timezone.utc)
    return utc_dt.astimezone(venue_tz)


def venue_to_utc_datetime(venue_dt: datetime, db_manager) -> datetime:
    """Convert venue local time to UTC"""
    venue_tz = get_venue_timezone(db_manager)
    if venue_dt.tzinfo is None:
        if HAS_PYTZ:
            venue_dt = venue_tz.localize(venue_dt)
        else:
            venue_dt = venue_dt.replace(tzinfo=venue_tz)
    return venue_dt.astimezone(timezone.utc)