from datetime import datetime, timedelta
from typing import Union, Optional


def format_datetime(dt: Union[datetime, str], format_str: str = "%d.%m.%Y %H:%M") -> str:
    if isinstance(dt, str):
        if dt == "now" or dt == "":
            dt = datetime.now()
        else:
            try:
                dt = datetime.fromisoformat(dt.replace('Z', '+00:00'))
            except (ValueError, AttributeError):
                dt = datetime.now()
    
    return dt.strftime(format_str)


def format_date(dt: Union[datetime, str], format_str: str = "%d.%m.%Y") -> str:
    if isinstance(dt, str):
        if dt == "now" or dt == "":
            dt = datetime.now()
        else:
            try:
                dt = datetime.fromisoformat(dt.replace('Z', '+00:00'))
            except (ValueError, AttributeError):
                dt = datetime.now()
    
    return dt.strftime(format_str)


def format_time_ago(dt: Union[datetime, str]) -> str:
    if isinstance(dt, str):
        if dt == "now" or dt == "":
            dt = datetime.now()
        else:
            try:
                dt = datetime.fromisoformat(dt.replace('Z', '+00:00'))
            except (ValueError, AttributeError):
                dt = datetime.now()
    
    now = datetime.utcnow()
    diff = now - dt
    
    if diff.days > 0:
        if diff.days == 1:
            return "вчера"
        elif diff.days < 7:
            return f"{diff.days} дн. назад"
        elif diff.days < 30:
            weeks = diff.days // 7
            return f"{weeks} нед. назад"
        elif diff.days < 365:
            months = diff.days // 30
            return f"{months} мес. назад"
        else:
            years = diff.days // 365
            return f"{years} г. назад"
    
    elif diff.seconds > 3600:
        hours = diff.seconds // 3600
        return f"{hours} ч. назад"
    
    elif diff.seconds > 60:
        minutes = diff.seconds // 60
        return f"{minutes} мин. назад"
    
    else:
        return "только что"

def format_days_declension(days: int, language: str = "ru") -> str:
    if language != "ru":
        return f"{days} day{'s' if days != 1 else ''}"
    
    if days % 10 == 1 and days % 100 != 11:
        return f"{days} день"
    elif days % 10 in [2, 3, 4] and days % 100 not in [12, 13, 14]:
        return f"{days} дня"
    else:
        return f"{days} дней"


def format_duration(seconds: int) -> str:
    if seconds < 60:
        return f"{seconds} сек."
    
    minutes = seconds // 60
    if minutes < 60:
        return f"{minutes} мин."
    
    hours = minutes // 60
    if hours < 24:
        return f"{hours} ч."
    
    days = hours // 24
    return f"{days} дн."


def format_bytes(bytes_value: int) -> str:
    if bytes_value == 0:
        return "0 B"
    
    units = ["B", "KB", "MB", "GB", "TB"]
    size = float(bytes_value)
    unit_index = 0
    
    while size >= 1024 and unit_index < len(units) - 1:
        size /= 1024
        unit_index += 1
    
    if size == int(size):
        return f"{int(size)} {units[unit_index]}"
    else:
        return f"{size:.1f} {units[unit_index]}"


def format_percentage(value: float, decimals: int = 1) -> str:
    return f"{value:.{decimals}f}%"


def format_number(number: Union[int, float], separator: str = " ") -> str:
    if isinstance(number, float):
        integer_part = int(number)
        decimal_part = number - integer_part
        
        formatted_integer = f"{integer_part:,}".replace(",", separator)
        
        if decimal_part > 0:
            return f"{formatted_integer}.{decimal_part:.2f}".split('.')[0] + f".{str(decimal_part).split('.')[1][:2]}"
        else:
            return formatted_integer
    else:
        return f"{number:,}".replace(",", separator)


def format_price_range(min_price: int, max_price: int) -> str:
    from app.config import settings
    
    min_formatted = settings.format_price(min_price)
    max_formatted = settings.format_price(max_price)
    
    if min_price == max_price:
        return min_formatted
    else:
        return f"{min_formatted} - {max_formatted}"


def truncate_text(text: str, max_length: int = 100, suffix: str = "...") -> str:
    if len(text) <= max_length:
        return text
    
    return text[:max_length - len(suffix)] + suffix


def format_username(username: Optional[str], user_id: int, full_name: Optional[str] = None) -> str:
    if full_name:
        return full_name
    elif username:
        return f"@{username}"
    else:
        return f"ID{user_id}"


def format_subscription_status(
    is_active: bool,
    is_trial: bool,
    end_date: Union[datetime, str],
    language: str = "ru"
) -> str:
    
    if isinstance(end_date, str):
        try:
            end_date = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
        except (ValueError, AttributeError):
            end_date = datetime.now()
    
    if not is_active:
        return "❌ Неактивна" if language == "ru" else "❌ Inactive"
    
    if is_trial:
        status = "🎁 Тестовая" if language == "ru" else "🎁 Trial"
    else:
        status = "✅ Активна" if language == "ru" else "✅ Active"
    
    now = datetime.utcnow()
    if end_date > now:
        days_left = (end_date - now).days
        if days_left > 0:
            status += f" ({days_left} дн.)" if language == "ru" else f" ({days_left} days)"
        else:
            hours_left = (end_date - now).seconds // 3600
            status += f" ({hours_left} ч.)" if language == "ru" else f" ({hours_left} hrs)"
    else:
        status = "⏰ Истекла" if language == "ru" else "⏰ Expired"
    
    return status


def format_traffic_usage(used_gb: float, limit_gb: int, language: str = "ru") -> str:
    
    if limit_gb == 0: 
        if language == "ru":
            return f"{used_gb:.1f} ГБ / ∞"
        else:
            return f"{used_gb:.1f} GB / ∞"
    
    percentage = (used_gb / limit_gb) * 100 if limit_gb > 0 else 0
    
    if language == "ru":
        return f"{used_gb:.1f} ГБ / {limit_gb} ГБ ({percentage:.1f}%)"
    else:
        return f"{used_gb:.1f} GB / {limit_gb} GB ({percentage:.1f}%)"


def format_boolean(value: bool, language: str = "ru") -> str:
    if language == "ru":
        return "✅ Да" if value else "❌ Нет"
    else:
        return "✅ Yes" if value else "❌ No"
