# online_state.py - 优化版本：添加缓存管理和清理机制
import threading
import time

# 在线玩家缓存
online_cache = {}          # key: 用户名, value: {'level': int, 'rebirth': int, 'map': str, 'sid': str, 'last_seen': float}
cache_lock = threading.Lock()

# 缓存统计信息
cache_stats = {
    'total_connections': 0,
    'peak_concurrent': 0,
    'last_cleanup': time.time()
}

def add_player_via_http(name, level, rebirth, map_id):
    """
    通过 HTTP 请求手动将玩家加入在线缓存（无 sid，临时状态）
    供登录/创建角色后立即调用，使其他功能能立即看到该玩家。
    """
    now = time.time()
    with cache_lock:
        info = online_cache.get(name)
        if info:
            # 如果已存在，只更新数据，保留原有的 sid（如果有）
            info['level'] = level
            info['rebirth'] = rebirth
            info['map'] = str(map_id)
            info['last_seen'] = now
            # 如果原有 sid 为 None，则保持 None；否则保留原 sid
        else:
            online_cache[name] = {
                'level': level,
                'rebirth': rebirth,
                'map': str(map_id),
                'sid': None,          # HTTP 添加的条目没有 sid
                'last_seen': now
            }
            cache_stats['total_connections'] += 1
            current_count = len(online_cache)
            if current_count > cache_stats['peak_concurrent']:
                cache_stats['peak_concurrent'] = current_count

def cleanup_offline_players():
    """清理超时离线玩家（超过120秒未心跳），HTTP 添加的无 sid 条目超过 60 秒无更新也清理"""
    global cache_stats
    now = time.time()
    expired = []
    
    with cache_lock:
        for name, info in list(online_cache.items()):
            if info['sid'] is None:
                # HTTP 添加的临时条目，超过 60 秒未更新则移除
                if now - info['last_seen'] > 60:
                    expired.append(name)
            else:
                # 正常 WebSocket 条目，超过 120 秒未心跳则移除
                if now - info['last_seen'] > 120:
                    expired.append(name)
        
        for name in expired:
            del online_cache[name]
            # 同步从状态管理器中移除（如果有）
            from state_manager import player_state_manager
            player_state_manager.remove(name)
        
        if expired:
            current_count = len(online_cache)
            if current_count > cache_stats['peak_concurrent']:
                cache_stats['peak_concurrent'] = current_count
            cache_stats['last_cleanup'] = now
    
    return len(expired)

def get_online_count():
    """获取当前在线人数"""
    with cache_lock:
        return len(online_cache)

def get_online_list():
    """获取在线列表（只读副本）"""
    with cache_lock:
        return [{
            'name': name,
            'level': info['level'],
            'rebirth': info['rebirth'],
            'map': info['map']
        } for name, info in online_cache.items()]

def update_player_info(name, level, rebirth, map_id, sid):
    """更新玩家信息"""
    now = time.time()
    changed = False
    
    with cache_lock:
        info = online_cache.get(name)
        if info:
            if (info['level'] != level or 
                info['rebirth'] != rebirth or 
                info['map'] != map_id):
                info['level'] = level
                info['rebirth'] = rebirth
                info['map'] = map_id
                changed = True
            info['last_seen'] = now
            info['sid'] = sid
        else:
            online_cache[name] = {
                'level': level,
                'rebirth': rebirth,
                'map': map_id,
                'sid': sid,
                'last_seen': now
            }
            changed = True
            cache_stats['total_connections'] += 1
            
            current_count = len(online_cache)
            if current_count > cache_stats['peak_concurrent']:
                cache_stats['peak_concurrent'] = current_count
    
    return changed

def remove_player(sid):
    """根据SID移除玩家"""
    removed_name = None
    with cache_lock:
        for name, info in list(online_cache.items()):
            if info['sid'] == sid:
                removed_name = name
                del online_cache[name]
                break
    return removed_name

# 启动后台清理线程
def start_cleaner():
    def cleaner():
        while True:
            time.sleep(60)  # 每分钟清理一次
            cleaned = cleanup_offline_players()
            if cleaned > 0:
                print(f"清理了 {cleaned} 个离线玩家，当前在线: {get_online_count()}")
    
    thread = threading.Thread(target=cleaner, daemon=True)
    thread.start()

# 自动启动清理器
start_cleaner()