from typing import Optional
from sqlalchemy.orm import Session
from database import Achievement, UserAchievement, ActivityFeed
from datetime import datetime
import json

# ─── Определения достижений ─────────────────────────────────────────────────

ACHIEVEMENT_DEFS = [
    {
        "name": "first_case",
        "title": "Первый шаг",
        "description": "Открой свой первый кейс",
        "icon": "📦",
        "category": "cases",
        "requirement_type": "open_cases",
        "requirement_value": 1,
        "reward_amount": 100,
        "sort_order": 1,
    },
    {
        "name": "case_collector_10",
        "title": "Коллекционер",
        "description": "Открой 10 кейсов",
        "icon": "📦",
        "category": "cases",
        "requirement_type": "open_cases",
        "requirement_value": 10,
        "reward_amount": 250,
        "sort_order": 2,
    },
    {
        "name": "case_collector_100",
        "title": "Заядлый коллекционер",
        "description": "Открой 100 кейсов",
        "icon": "📦",
        "category": "cases",
        "requirement_type": "open_cases",
        "requirement_value": 100,
        "reward_amount": 1000,
        "sort_order": 3,
    },
    {
        "name": "case_collector_1000",
        "title": "Одержимый",
        "description": "Открой 1000 кейсов",
        "icon": "💎",
        "category": "cases",
        "requirement_type": "open_cases",
        "requirement_value": 1000,
        "reward_amount": 5000,
        "sort_order": 4,
    },
    {
        "name": "first_contract",
        "title": "Обменщик",
        "description": "Выполни первый контракт обмена",
        "icon": "🔄",
        "category": "contracts",
        "requirement_type": "contracts",
        "requirement_value": 1,
        "reward_amount": 200,
        "sort_order": 5,
    },
    {
        "name": "contract_master",
        "title": "Мастер контрактов",
        "description": "Выполни 50 контрактов обмена",
        "icon": "🔄",
        "category": "contracts",
        "requirement_type": "contracts",
        "requirement_value": 50,
        "reward_amount": 2000,
        "sort_order": 6,
    },
    {
        "name": "first_upgrade",
        "title": "Рисковый",
        "description": "Попробуй апгрейд в первый раз",
        "icon": "🆙",
        "category": "upgrade",
        "requirement_type": "upgrade_attempts",
        "requirement_value": 1,
        "reward_amount": 100,
        "sort_order": 7,
    },
    {
        "name": "upgrade_winner",
        "title": "Везунчик",
        "description": "Выиграй 10 апгрейдов",
        "icon": "🍀",
        "category": "upgrade",
        "requirement_type": "upgrade_wins",
        "requirement_value": 10,
        "reward_amount": 1500,
        "sort_order": 8,
    },
    {
        "name": "rare_finder",
        "title": "Охотник за редким",
        "description": "Выбей предмет редкости Covert или Rare Special",
        "icon": "🔴",
        "category": "cases",
        "requirement_type": "rare_item",
        "requirement_value": 1,
        "reward_amount": 500,
        "sort_order": 9,
    },
    {
        "name": "knife_collector",
        "title": "Ножевод",
        "description": "Выбей нож или перчатки",
        "icon": "🔪",
        "category": "cases",
        "requirement_type": "knife",
        "requirement_value": 1,
        "reward_amount": 2000,
        "sort_order": 10,
    },
    {
        "name": "big_spender",
        "title": "Транжира",
        "description": "Потрать 10000 ₽ на кейсы",
        "icon": "💰",
        "category": "general",
        "requirement_type": "total_spent",
        "requirement_value": 10000,
        "reward_amount": 1000,
        "sort_order": 11,
    },
    {
        "name": "whale",
        "title": "Кит",
        "description": "Потрать 100000 ₽ на кейсы",
        "icon": "🐋",
        "category": "general",
        "requirement_type": "total_spent",
        "requirement_value": 100000,
        "reward_amount": 10000,
        "sort_order": 12,
    },
    {
        "name": "slot_winner",
        "title": "Джекпот",
        "description": "Собери 3 одинаковых символа в слот-машине",
        "icon": "🎰",
        "category": "cases",
        "requirement_type": "slot_match",
        "requirement_value": 1,
        "reward_amount": 1000,
        "sort_order": 13,
    },
    {
        "name": "rich_100k",
        "title": "Богач",
        "description": "Накопи 100000 ₽ на балансе",
        "icon": "🤑",
        "category": "general",
        "requirement_type": "balance_100k",
        "requirement_value": 1,
        "reward_amount": 5000,
        "sort_order": 14,
    },
    {
        "name": "slots_10",
        "title": "Слото-фанат",
        "description": "Сыграй 10 раундов в слот-машине",
        "icon": "🎰",
        "category": "cases",
        "requirement_type": "slot_plays",
        "requirement_value": 10,
        "reward_amount": 500,
        "sort_order": 15,
    },
    {
        "name": "crash_first",
        "title": "Крэш-тестер",
        "description": "Сыграй в Crash в первый раз",
        "icon": "💥",
        "category": "crash",
        "requirement_type": "crash_plays",
        "requirement_value": 1,
        "reward_amount": 100,
        "sort_order": 16,
    },
    {
        "name": "crash_pro",
        "title": "Крэш-профи",
        "description": "Сыграй 50 раундов в Crash",
        "icon": "💥",
        "category": "crash",
        "requirement_type": "crash_plays",
        "requirement_value": 50,
        "reward_amount": 2000,
        "sort_order": 17,
    },
    {
        "name": "crash_5x",
        "title": "Смельчак",
        "description": "Выведи деньги на множителе x5 или выше в Crash",
        "icon": "🚀",
        "category": "crash",
        "requirement_type": "crash_cashout_5x",
        "requirement_value": 1,
        "reward_amount": 1500,
        "sort_order": 18,
    },
    {
        "name": "inventory_50",
        "title": "Собиратель",
        "description": "Собери 50 предметов в инвентаре",
        "icon": "🎒",
        "category": "general",
        "requirement_type": "inventory_count",
        "requirement_value": 50,
        "reward_amount": 500,
        "sort_order": 19,
    },
]


def seed_achievements(db: Session):
    """Создаёт достижения в БД если их ещё нет"""
    existing = db.query(Achievement).count()
    if existing > 0:
        return
    
    for defn in ACHIEVEMENT_DEFS:
        ach = Achievement(**defn)
        db.add(ach)
    db.commit()


def get_or_create_user_achievement(db: Session, user_id: int, achievement_id: int) -> UserAchievement:
    ua = db.query(UserAchievement).filter(
        UserAchievement.user_id == user_id,
        UserAchievement.achievement_id == achievement_id
    ).first()
    if not ua:
        ua = UserAchievement(user_id=user_id, achievement_id=achievement_id)
        db.add(ua)
        db.commit()
        db.refresh(ua)
    return ua


def check_achievement(db: Session, user_id: int, achievement_name: str, current_value: int) -> Optional[dict]:
    """Проверяет и разблокирует достижение. Возвращает dict с инфой если разблокировано."""
    ach = db.query(Achievement).filter(Achievement.name == achievement_name).first()
    if not ach:
        return None
    
    ua = get_or_create_user_achievement(db, user_id, ach.id)
    if ua.unlocked_at:
        return None
    
    ua.progress = min(current_value, ach.requirement_value)
    
    if current_value >= ach.requirement_value:
        ua.unlocked_at = datetime.utcnow()
        # Награда
        from database import User
        user = db.query(User).filter(User.id == user_id).first()
        if user:
            user.balance += ach.reward_amount
        db.commit()
        
        # Запись в ленту активности
        activity = ActivityFeed(
            user_id=user_id,
            username=user.username if user else "unknown",
            activity_type="achievement",
            message=f"🏆 Получено достижение: {ach.title}",
            data_json=json.dumps({
                "achievement_name": ach.name,
                "achievement_title": ach.title,
                "achievement_icon": ach.icon,
            })
        )
        db.add(activity)
        db.commit()
        
        return {
            "name": ach.name,
            "title": ach.title,
            "icon": ach.icon,
            "reward": ach.reward_amount
        }
    
    db.commit()
    return None


def check_open_cases_achievements(db: Session, user_id: int):
    from database import CaseOpening
    count = db.query(CaseOpening).filter(CaseOpening.user_id == user_id).count()
    
    results = []
    for ach_name in ["first_case", "case_collector_10", "case_collector_100", "case_collector_1000"]:
        r = check_achievement(db, user_id, ach_name, count)
        if r:
            results.append(r)
    return results


def check_contracts_achievements(db: Session, user_id: int):
    from database import Contract
    count = db.query(Contract).filter(Contract.user_id == user_id).count()
    
    results = []
    for ach_name in ["first_contract", "contract_master"]:
        r = check_achievement(db, user_id, ach_name, count)
        if r:
            results.append(r)
    return results


def check_upgrade_achievements(db: Session, user_id: int):
    from database import Upgrade
    attempts = db.query(Upgrade).filter(Upgrade.user_id == user_id).count()
    wins = db.query(Upgrade).filter(Upgrade.user_id == user_id, Upgrade.success == True).count()
    
    results = []
    r1 = check_achievement(db, user_id, "first_upgrade", attempts)
    if r1: results.append(r1)
    r2 = check_achievement(db, user_id, "upgrade_winner", wins)
    if r2: results.append(r2)
    return results


def check_rare_item_achievement(db: Session, user_id: int, rarity: str):
    results = []
    if rarity in ("Covert", "Extraordinary", "Rare Special Item"):
        r = check_achievement(db, user_id, "rare_finder", 1)
        if r: results.append(r)
    return results


def check_knife_achievement(db: Session, user_id: int, item_data: dict):
    from backend import is_knife, is_gloves
    results = []
    if is_knife(item_data) or is_gloves(item_data):
        r = check_achievement(db, user_id, "knife_collector", 1)
        if r: results.append(r)
    return results


def check_spent_achievements(db: Session, user_id: int, total_spent: float):
    results = []
    r1 = check_achievement(db, user_id, "big_spender", int(total_spent))
    if r1: results.append(r1)
    r2 = check_achievement(db, user_id, "whale", int(total_spent))
    if r2: results.append(r2)
    return results


def check_balance_achievement(db: Session, user_id: int):
    from database import User
    user = db.query(User).filter(User.id == user_id).first()
    if user and user.balance >= 100000:
        r = check_achievement(db, user_id, "rich_100k", 1)
        if r: return [r]
    return []


def check_slot_match_achievement(db: Session, user_id: int):
    results = []
    r = check_achievement(db, user_id, "slot_winner", 1)
    if r: results.append(r)
    return results


def check_slot_plays_achievements(db: Session, user_id: int):
    from database import CaseOpening
    slot_count = db.query(CaseOpening).filter(
        CaseOpening.user_id == user_id,
        CaseOpening.case_name.ilike("%slot%")
    ).count()
    results = []
    r = check_achievement(db, user_id, "slots_10", slot_count)
    if r: results.append(r)
    return results


def check_inventory_achievement(db: Session, user_id: int):
    from database import InventoryItem
    count = db.query(InventoryItem).filter(InventoryItem.user_id == user_id).count()
    results = []
    r = check_achievement(db, user_id, "inventory_50", count)
    if r: results.append(r)
    return results


def get_user_achievements(db: Session, user_id: int) -> list:
    """Возвращает все достижения пользователя с прогрессом"""
    all_ach = db.query(Achievement).order_by(Achievement.sort_order).all()
    result = []
    for ach in all_ach:
        ua = db.query(UserAchievement).filter(
            UserAchievement.user_id == user_id,
            UserAchievement.achievement_id == ach.id
        ).first()
        result.append({
            "id": ach.id,
            "name": ach.name,
            "title": ach.title,
            "description": ach.description,
            "icon": ach.icon,
            "category": ach.category,
            "requirement_type": ach.requirement_type,
            "requirement_value": ach.requirement_value,
            "reward_amount": ach.reward_amount,
            "progress": ua.progress if ua else 0,
            "unlocked": ua.unlocked_at is not None if ua else False,
            "unlocked_at": ua.unlocked_at.isoformat() if ua and ua.unlocked_at else None,
        })
    return result
