import random
from datetime import datetime
from typing import Dict, Optional
from sqlalchemy.orm import Session
from database import User, UserRPU

# Стандартные веса редкостей
BASE_RARITY_WEIGHTS = {
    "Consumer Grade": 10000,
    "Industrial Grade": 5000,
    "Mil-Spec": 2500,
    "Mil-Spec Grade": 2500,
    "Restricted": 625,
    "Classified": 125,
    "Covert": 25,
    "Rare Special Item": 5,
    "Extraordinary": 5
}

# Маппинг редкостей на поля в UserRPU
RARITY_TO_FIELD = {
    "Consumer Grade": "consumer_multiplier",
    "Industrial Grade": "industrial_multiplier",
    "Mil-Spec": "mil_spec_multiplier",
    "Mil-Spec Grade": "mil_spec_multiplier",
    "Restricted": "restricted_multiplier",
    "Classified": "classified_multiplier",
    "Covert": "covert_multiplier",
    "Rare Special Item": "rare_special_multiplier",
    "Extraordinary": "rare_special_multiplier"
}


def get_user_rpu(db: Session, user_id: int) -> UserRPU:
    """Получает или создает настройки РПУ для пользователя"""
    rpu = db.query(UserRPU).filter(UserRPU.user_id == user_id).first()
    if not rpu:
        rpu = UserRPU(user_id=user_id)
        db.add(rpu)
        db.commit()
        db.refresh(rpu)
    return rpu


def get_adjusted_weights(db: Session, user_id: int) -> Dict[str, float]:
    """
    Получает веса редкостей с учетом РПУ пользователя.
    НИЗКИЙ % РПУ = ПОВЫШЕННЫЕ шансы на редкое (везёт)
    ВЫСОКИЙ % РПУ = ПОНИЖЕННЫЕ шансы на редкое (не везёт)
    """
    rpu = get_user_rpu(db, user_id)
    
    # Вычисляем общий уровень РПУ (0-100%)
    rpu_level = calculate_rpu_level(rpu)
    
    # Переворачиваем: низкий РПУ = высокий множитель для редких
    # При 0% РПУ множитель для редких = 2.0 (очень везёт)
    # При 50% РПУ множитель = 1.0 (обычно)
    # При 100% РПУ множитель = 0.1 (совсем не везёт)
    
    adjusted = {}
    for rarity, base_weight in BASE_RARITY_WEIGHTS.items():
        field = RARITY_TO_FIELD.get(rarity)
        base_multiplier = getattr(rpu, field, 1.0) if field else 1.0
        
        # Определяем "редкость" предмета (чем реже, тем больше индекс)
        rarity_index = 0
        if "Industrial" in rarity:
            rarity_index = 1
        elif "Mil-Spec" in rarity:
            rarity_index = 2
        elif "Restricted" in rarity:
            rarity_index = 3
        elif "Classified" in rarity:
            rarity_index = 4
        elif "Covert" in rarity:
            rarity_index = 5
        elif "Rare Special" in rarity or "Extraordinary" in rarity:
            rarity_index = 6
        
        # Чем выше РПУ, тем сильнее режем шансы на редкое
        # Чем ниже РПУ, тем сильнее повышаем шансы на редкое
        if rpu_level < 50:
            # Везёт: повышаем шансы на редкое
            luck_factor = 1.0 + ((50 - rpu_level) / 50) * rarity_index * 0.3
        else:
            # Не везёт: понижаем шансы на редкое
            luck_factor = 1.0 - ((rpu_level - 50) / 50) * rarity_index * 0.2
        
        luck_factor = max(0.1, min(3.0, luck_factor))
        
        final_multiplier = base_multiplier * rpu.luck_multiplier * luck_factor
        adjusted[rarity] = base_weight * final_multiplier
    
    return adjusted


def calculate_rpu_level(rpu: UserRPU) -> float:
    """
    Вычисляет общий уровень РПУ (0-100%).
    0% = максимальное везение
    100% = максимальное невезение
    """
    multipliers = [
        rpu.consumer_multiplier,
        rpu.industrial_multiplier,
        rpu.mil_spec_multiplier,
        rpu.restricted_multiplier,
        rpu.classified_multiplier,
        rpu.covert_multiplier,
        rpu.rare_special_multiplier
    ]
    
    # Средний множитель
    avg = sum(multipliers) / len(multipliers)
    
    # Преобразуем в проценты: 0.1x = 100% РПУ (не везёт), 3.0x = 0% РПУ (везёт)
    # 1.0x = 50% РПУ
    if avg >= 1.0:
        level = 50 - ((avg - 1.0) / 2.0) * 100
    else:
        level = 50 + ((1.0 - avg) / 0.9) * 50
    
    return max(0, min(100, level))


def get_rpu_description(level: float) -> str:
    """Возвращает текстовое описание уровня РПУ"""
    if level < 20:
        return "🍀 Очень везучий"
    elif level < 35:
        return "😊 Везучий"
    elif level < 45:
        return "🙂 Немного везучий"
    elif level < 55:
        return "😐 Обычный"
    elif level < 70:
        return "🙁 Немного невезучий"
    elif level < 85:
        return "😟 Невезучий"
    else:
        return "💀 Проклятый"


def auto_adjust_rpu(db: Session, user_id: int):
    """Автоматическая подкрутка РПУ на основе статистики"""
    rpu = get_user_rpu(db, user_id)
    
    if not rpu.auto_adjust:
        return
    
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        return
    
    # Анализируем статистику
    if rpu.total_opened > 0:
        avg_spent_per_case = rpu.total_spent / rpu.total_opened
        
        # Если пользователь много тратит и мало получает - снижаем РПУ (даём везение)
        if rpu.total_spent > 10000 and rpu.total_opened > 20:
            # Снижаем РПУ на 5-15%
            reduction = min(0.15, rpu.total_spent / 100000)
            rpu.luck_multiplier = min(2.0, rpu.luck_multiplier + reduction)
        
        # Если пользователь часто открывает кейсы - немного снижаем РПУ
        if rpu.total_opened > 50:
            rpu.classified_multiplier = min(1.5, rpu.classified_multiplier + 0.05)
            rpu.covert_multiplier = min(1.3, rpu.covert_multiplier + 0.03)
    
    # Ограничиваем множители
    for field in ['consumer_multiplier', 'industrial_multiplier', 'mil_spec_multiplier',
                  'restricted_multiplier', 'classified_multiplier', 'covert_multiplier',
                  'rare_special_multiplier']:
        value = getattr(rpu, field)
        setattr(rpu, field, max(0.1, min(3.0, value)))
    
    rpu.luck_multiplier = max(0.1, min(3.0, rpu.luck_multiplier))
    rpu.last_adjustment = datetime.utcnow()
    db.commit()


def update_rpu_stats(db: Session, user_id: int, spent: float, opened: int = 1):
    """Обновляет статистику РПУ после открытия кейсов"""
    rpu = get_user_rpu(db, user_id)
    rpu.total_spent += spent
    rpu.total_opened += opened
    db.commit()
    
    # Авто-подкрутка если включена
    if rpu.auto_adjust:
        auto_adjust_rpu(db, user_id)