"""
Утилиты для работы с пользователями.
"""
import re
from django.utils import timezone
import pytz


def normalize_phone(value):
    """
    Нормализует номер телефона к формату +999999999 (до 15 цифр).
    Принимает ввод с пробелами, скобками, дефисами и т.д.
    """
    if not value or not isinstance(value, str):
        return ''
    digits = re.sub(r'\D', '', value)
    if not digits:
        return ''
    # Россия: 8XXXXXXXXXX -> +7..., 7XXXXXXXXXX -> +7..., 9XXXXXXXXX -> +79...
    if len(digits) == 11 and digits[0] == '8':
        digits = '7' + digits[1:]
    elif len(digits) == 10 and digits[0] == '9':
        digits = '7' + digits
    elif len(digits) == 11 and digits[0] == '7':
        pass
    return '+' + digits[:15]


def convert_to_user_timezone(dt, user_timezone='UTC'):
    """
    Конвертирует datetime из UTC в часовой пояс пользователя.
    
    Args:
        dt: datetime объект (должен быть aware в UTC)
        user_timezone: строка с названием часового пояса (например, 'Europe/Moscow' или 'UTC+10')
    
    Returns:
        datetime объект в часовом поясе пользователя
    """
    if dt is None:
        return None
    
    try:
        # Нормализуем часовой пояс
        # Если передан формат UTC+X или UTC-X, конвертируем в Etc/GMT±X
        normalized_tz = (user_timezone or 'UTC').strip()
        
        # Обрабатываем формат UTC+X или UTC-X
        if normalized_tz.upper().startswith('UTC'):
            # Обрабатываем UTC+X или UTC-X
            # Убираем "UTC" (регистронезависимо)
            offset_str = normalized_tz[3:].strip()  # Убираем "UTC"
            
            if offset_str.startswith('+'):
                # UTC+10 -> Etc/GMT-10 (обратите внимание на минус! В Etc/GMT знак инвертирован)
                try:
                    offset_hours = int(offset_str[1:])
                    normalized_tz = f'Etc/GMT-{offset_hours}'
                except (ValueError, IndexError):
                    normalized_tz = 'UTC'
            elif offset_str.startswith('-'):
                # UTC-5 -> Etc/GMT+5 (обратите внимание на плюс! В Etc/GMT знак инвертирован)
                try:
                    offset_hours = int(offset_str[1:])
                    normalized_tz = f'Etc/GMT+{offset_hours}'
                except (ValueError, IndexError):
                    normalized_tz = 'UTC'
            elif offset_str == '':
                # UTC -> UTC
                normalized_tz = 'UTC'
            else:
                # Если формат не распознан (например, UTC+10:00 или другой формат), используем UTC
                normalized_tz = 'UTC'
        
        # Получаем часовой пояс пользователя
        # Если normalized_tz все еще 'UTC+10' (не был обработан), пробуем еще раз
        if normalized_tz.startswith('UTC') and normalized_tz != 'UTC':
            # Если дошли сюда, значит формат не был распознан выше
            # Пробуем конвертировать еще раз
            offset_str = normalized_tz[3:].strip()
            if offset_str.startswith('+'):
                try:
                    offset_hours = int(offset_str[1:])
                    normalized_tz = f'Etc/GMT-{offset_hours}'
                except (ValueError, IndexError):
                    normalized_tz = 'UTC'
            elif offset_str.startswith('-'):
                try:
                    offset_hours = int(offset_str[1:])
                    normalized_tz = f'Etc/GMT+{offset_hours}'
                except (ValueError, IndexError):
                    normalized_tz = 'UTC'
        
        # Получаем часовой пояс пользователя
        tz = pytz.timezone(normalized_tz)
        
        # Если datetime не aware, делаем его aware в UTC
        if timezone.is_naive(dt):
            dt = timezone.make_aware(dt, pytz.UTC)
        
        # Конвертируем в часовой пояс пользователя
        return dt.astimezone(tz)
    except (pytz.exceptions.UnknownTimeZoneError, ValueError, Exception) as e:
        # Если часовой пояс неизвестен или произошла ошибка, возвращаем как есть
        # Логируем ошибку для отладки
        import logging
        logger = logging.getLogger(__name__)
        logger.warning(f"Error converting timezone {user_timezone}: {e}")
        return dt


def get_user_timezone(user_timezone='UTC'):
    """
    Получить объект timezone для часового пояса пользователя.
    Обрабатывает формат UTC+X и UTC-X.

    Args:
        user_timezone: строка с названием часового пояса (например, 'Europe/Moscow' или 'UTC+10')

    Returns:
        pytz timezone объект
    """
    if not user_timezone:
        return pytz.UTC

    normalized_tz = user_timezone.strip()

    # Обрабатываем формат UTC+X или UTC-X
    if normalized_tz.upper().startswith('UTC'):
        offset_str = normalized_tz[3:].strip()

        if offset_str.startswith('+'):
            try:
                offset_hours = int(offset_str[1:])
                normalized_tz = f'Etc/GMT-{offset_hours}'
            except (ValueError, IndexError):
                normalized_tz = 'UTC'
        elif offset_str.startswith('-'):
            try:
                offset_hours = int(offset_str[1:])
                normalized_tz = f'Etc/GMT+{offset_hours}'
            except (ValueError, IndexError):
                normalized_tz = 'UTC'
        elif offset_str == '':
            normalized_tz = 'UTC'
        else:
            normalized_tz = 'UTC'

    try:
        return pytz.timezone(normalized_tz)
    except pytz.exceptions.UnknownTimeZoneError:
        import logging
        logger = logging.getLogger(__name__)
        logger.warning(f"Unknown timezone {user_timezone}, using UTC")
        return pytz.UTC


def format_datetime_for_user(dt, user_timezone='UTC', format_str='isoformat'):
    """
    Форматирует datetime в часовой пояс пользователя и возвращает строку.

    Args:
        dt: datetime объект (должен быть aware в UTC)
        user_timezone: строка с названием часового пояса
        format_str: формат вывода ('isoformat' для ISO строки, или strftime формат)

    Returns:
        строка с датой и временем в часовом поясе пользователя
    """
    if dt is None:
        return None

    local_dt = convert_to_user_timezone(dt, user_timezone)

    if format_str == 'isoformat':
        # Убеждаемся, что isoformat() возвращает строку с timezone offset
        # Для pytz timezone isoformat() должен автоматически включать offset
        # Но для Etc/GMT timezone может быть проблема, поэтому добавляем offset вручную
        if local_dt.tzinfo:
            # Получаем offset в секундах
            offset = local_dt.utcoffset()
            if offset:
                # Формируем ISO строку с offset вручную для гарантии правильного формата
                # Формат: YYYY-MM-DDTHH:MM:SS+HH:MM или YYYY-MM-DDTHH:MM:SS-HH:MM
                total_seconds = int(offset.total_seconds())
                hours = total_seconds // 3600
                minutes = (total_seconds % 3600) // 60
                sign = '+' if hours >= 0 else '-'
                
                # Форматируем дату и время без timezone
                dt_str = local_dt.strftime('%Y-%m-%dT%H:%M:%S')
                # Добавляем миллисекунды, если есть
                if local_dt.microsecond:
                    dt_str += f".{local_dt.microsecond // 1000:03d}"
                
                # Добавляем offset
                iso_str = f"{dt_str}{sign}{abs(hours):02d}:{abs(minutes):02d}"
            else:
                # Если offset равен 0, используем Z для UTC
                iso_str = local_dt.strftime('%Y-%m-%dT%H:%M:%S')
                if local_dt.microsecond:
                    iso_str += f".{local_dt.microsecond // 1000:03d}"
                iso_str += 'Z'
        else:
            # Если нет timezone, просто возвращаем ISO строку
            iso_str = local_dt.isoformat()
        
        return iso_str
    else:
        return local_dt.strftime(format_str)
