# parking.py
import time
import sqlite3
import math
import threading
import logging
from flask import Blueprint, request, jsonify, session
from jwt_utils import verify_token   # 导入 JWT 验证函数
from config_center import CONFIG

logger = logging.getLogger(__name__)
parking_bp = Blueprint('parking', __name__, url_prefix='/api/parking')

game_engine = None
socketio = None

def set_game_engine(engine):
    global game_engine
    game_engine = engine

# ========== 认证辅助函数 ==========
def _get_user_from_request(req):
    auth_header = req.headers.get('Authorization')
    if auth_header and auth_header.startswith('Bearer '):
        token = auth_header.split(' ')[1]
        payload = verify_token(token)
        if payload:
            return payload.get('user_id')
    return session.get('user_id')

def _verify_character_owner(character_name, user_id):
    if not character_name or not user_id:
        return False
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT user_id FROM characters WHERE name = ?', (character_name,))
        row = c.fetchone()
        return row is not None and row[0] == user_id
    finally:
        conn.close()

def init_parking(app, engine, socketio_instance):
    global game_engine, socketio
    game_engine = engine
    socketio = socketio_instance

    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        # 车辆配置表
        c.execute('''
            CREATE TABLE IF NOT EXISTS parking_vehicles (
                id INTEGER PRIMARY KEY,
                name TEXT NOT NULL,
                price INTEGER NOT NULL,
                exp_per_minute INTEGER NOT NULL,
                icon TEXT DEFAULT '🚗'
            )
        ''')
        # 玩家车辆表
        c.execute('''
            CREATE TABLE IF NOT EXISTS player_vehicles (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                player_name TEXT NOT NULL,
                vehicle_id INTEGER NOT NULL,
                is_selected BOOLEAN DEFAULT 0,
                level INTEGER DEFAULT 1,
                current_exp_per_minute INTEGER
            )
        ''')
        # 停车位表
        c.execute('''
            CREATE TABLE IF NOT EXISTS parking_spots (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                owner_name TEXT NOT NULL,
                spot_index INTEGER NOT NULL,
                parked_by TEXT,
                vehicle_instance_id INTEGER,
                start_time INTEGER,
                last_claim_time INTEGER,
                last_rent_time INTEGER,
                UNIQUE(owner_name, spot_index)
            )
        ''')
        # 每日经验表（不再使用，但保留表结构）
        c.execute('''
            CREATE TABLE IF NOT EXISTS vehicle_daily_exp (
                vehicle_instance_id INTEGER NOT NULL,
                date TEXT NOT NULL,
                exp_gained_today INTEGER DEFAULT 0,
                PRIMARY KEY (vehicle_instance_id, date)
            )
        ''')

        # 插入默认车辆（从 config.json 读取）
        vehicles_data = CONFIG.get('parking_vehicles', [])
        for v in vehicles_data:
            c.execute('''
                INSERT OR IGNORE INTO parking_vehicles 
                (id, name, price, exp_per_minute, icon) 
                VALUES (?, ?, ?, ?, ?)
            ''', (v['id'], v['name'], v['price'], v['exp_per_minute'], v['icon']))
        conn.commit()
    finally:
        conn.close()

    app.register_blueprint(parking_bp)
    threading.Thread(target=auto_cleanup_parking, daemon=True).start()

def add_exp_and_gold(state, exp, gold):
    state['player']['gold'] += gold
    hero = state.get('hero')
    if hero and hero.get('summoned') and exp > 0:
        player_exp = exp // 2 + (exp % 2)
        hero_exp = exp // 2
    else:
        player_exp = exp
        hero_exp = 0

    state['player']['exp'] += player_exp
    if game_engine:
        if 'log_messages' not in state:
            state['log_messages'] = []
        state = game_engine._check_level_up(state, 'player')

    if hero_exp > 0:
        hero['exp'] = hero.get('exp', 0) + hero_exp
        if game_engine:
            state = game_engine._check_level_up(state, 'hero')

    return state

# ========== 通用数据获取函数 ==========
def get_player_state(player_name):
    from state_manager import player_state_manager
    state = player_state_manager.get(player_name)
    if state is None:
        from db_storage import load_state_from_tables
        state = load_state_from_tables(player_name)
        if state:
            player_state_manager.set(player_name, state)
    return state

def save_player_state(player_name, state):
    from state_manager import player_state_manager
    player_state_manager.set(player_name, state)

def get_vehicle_info(vehicle_id):
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT * FROM parking_vehicles WHERE id = ?', (vehicle_id,))
        row = c.fetchone()
        if row:
            return {'id': row[0], 'name': row[1], 'price': row[2], 'exp_per_minute': row[3], 'icon': row[4]}
        return None
    finally:
        conn.close()

def get_vehicle_instance(instance_id):
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT player_name, vehicle_id, level, current_exp_per_minute FROM player_vehicles WHERE id = ?', (instance_id,))
        row = c.fetchone()
        if row:
            return {
                'player_name': row[0],
                'vehicle_id': row[1],
                'level': row[2],
                'current_exp_per_minute': row[3]
            }
        return None
    finally:
        conn.close()

def ensure_parking_spots(owner_name):
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        max_spots = CONFIG.get('parking', {}).get('max_spots_per_player', 6)
        for i in range(1, max_spots + 1):
            c.execute('INSERT OR IGNORE INTO parking_spots (owner_name, spot_index, parked_by, vehicle_instance_id, start_time, last_claim_time, last_rent_time) VALUES (?, ?, NULL, NULL, NULL, NULL, NULL)', (owner_name, i))
        conn.commit()
    finally:
        conn.close()

def get_parking_spot(owner_name, spot_index):
    conn = sqlite3.connect('chat.db')
    conn.row_factory = sqlite3.Row
    try:
        c = conn.cursor()
        c.execute('SELECT * FROM parking_spots WHERE owner_name = ? AND spot_index = ?', (owner_name, spot_index))
        row = c.fetchone()
        return dict(row) if row else None
    finally:
        conn.close()

def update_parking_spot(owner_name, spot_index, parked_by, vehicle_instance_id, start_time):
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        now = int(time.time())
        c.execute('''
            UPDATE parking_spots 
            SET parked_by = ?, vehicle_instance_id = ?, start_time = ?, last_claim_time = ?, last_rent_time = NULL
            WHERE owner_name = ? AND spot_index = ?
        ''', (parked_by, vehicle_instance_id, start_time, now, owner_name, spot_index))
        conn.commit()
    finally:
        conn.close()

def clear_parking_spot(owner_name, spot_index):
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('UPDATE parking_spots SET parked_by = NULL, vehicle_instance_id = NULL, start_time = NULL, last_claim_time = NULL, last_rent_time = NULL WHERE owner_name = ? AND spot_index = ?', (owner_name, spot_index))
        conn.commit()
    finally:
        conn.close()

# ========== 每日上限相关函数（已废弃，保留空实现，但不再调用） ==========
def get_today_str():
    return time.strftime("%Y-%m-%d")

def get_vehicle_daily_cap(base_exp_per_minute):
    return 10**12

def get_remaining_daily_exp(instance_id, base_exp_per_minute):
    return 10**12

def add_daily_exp(instance_id, exp_gained):
    return exp_gained

# ========== API 路由 ==========
@parking_bp.route('/vehicles', methods=['GET'])
def list_vehicles():
    conn = sqlite3.connect('chat.db')
    conn.row_factory = sqlite3.Row
    try:
        c = conn.cursor()
        c.execute('SELECT * FROM parking_vehicles ORDER BY price')
        rows = c.fetchall()
        return jsonify([dict(r) for r in rows])
    finally:
        conn.close()

@parking_bp.route('/my_vehicles', methods=['GET'])
def my_vehicles():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    player_name = request.args.get('name')
    if not player_name:
        return jsonify({'error': '缺少角色名'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权访问此角色'}), 403

    conn = sqlite3.connect('chat.db')
    conn.row_factory = sqlite3.Row
    try:
        c = conn.cursor()
        c.execute('''
            SELECT pv.id as instance_id, pv.vehicle_id, pv.is_selected, pv.level, 
                   COALESCE(pv.current_exp_per_minute, v.exp_per_minute) as exp_per_minute,
                   v.name, v.price, v.icon
            FROM player_vehicles pv
            JOIN parking_vehicles v ON pv.vehicle_id = v.id
            WHERE pv.player_name = ?
            ORDER BY pv.id
        ''', (player_name,))
        rows = c.fetchall()
        vehicles = []
        for row in rows:
            v = dict(row)
            v['remaining_exp'] = 10**12   # 无每日上限
            vehicles.append(v)
        selected_id = next((v['instance_id'] for v in vehicles if v['is_selected']), None)
        return jsonify({'vehicles': vehicles, 'selected_instance_id': selected_id})
    finally:
        conn.close()

@parking_bp.route('/buy', methods=['POST'])
def buy_vehicle():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    player_name = data.get('player_name')
    vehicle_id = data.get('vehicle_id')
    if not player_name or not vehicle_id:
        return jsonify({'error': '参数不足'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403

    state = get_player_state(player_name)
    if not state:
        return jsonify({'error': '角色不存在'}), 404
    vehicle = get_vehicle_info(vehicle_id)
    if not vehicle:
        return jsonify({'error': '车辆不存在'}), 400
    if state['player']['gold'] < vehicle['price']:
        return jsonify({'error': f'金币不足，需要{vehicle["price"]}金币'}), 400

    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        state['player']['gold'] -= vehicle['price']
        if 'userId' not in state:
            c.execute('SELECT user_id FROM characters WHERE name = ?', (player_name,))
            row = c.fetchone()
            if row and row[0]:
                state['userId'] = row[0]
            else:
                state['userId'] = 0
        save_player_state(player_name, state)
        c.execute('''
            INSERT INTO player_vehicles (player_name, vehicle_id, is_selected, level, current_exp_per_minute)
            VALUES (?, ?, ?, ?, ?)
        ''', (player_name, vehicle_id, 0, 1, vehicle['exp_per_minute']))
        # 创建车位（如果还没有）
        c.execute('SELECT COUNT(*) FROM parking_spots WHERE owner_name = ?', (player_name,))
        if c.fetchone()[0] == 0:
            ensure_parking_spots(player_name)
        conn.commit()
        return jsonify({'success': True, 'message': f'成功购买 {vehicle["name"]}'})
    except Exception as e:
        conn.rollback()
        return jsonify({'error': f'购买失败: {str(e)}'}), 500
    finally:
        conn.close()

@parking_bp.route('/select_vehicle', methods=['POST'])
def select_vehicle():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    player_name = data.get('player_name')
    instance_id = data.get('instance_id')
    if not player_name or not instance_id:
        return jsonify({'error': '参数不足'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403

    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT 1 FROM player_vehicles WHERE player_name = ? AND id = ?', (player_name, instance_id))
        if not c.fetchone():
            return jsonify({'error': '车辆实例不存在'}), 400
        c.execute('UPDATE player_vehicles SET is_selected = 0 WHERE player_name = ?', (player_name,))
        c.execute('UPDATE player_vehicles SET is_selected = 1 WHERE player_name = ? AND id = ?', (player_name, instance_id))
        conn.commit()
        return jsonify({'success': True, 'message': '已切换当前车辆'})
    finally:
        conn.close()

@parking_bp.route('/my_spots', methods=['GET'])
def my_spots():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    player_name = request.args.get('name')
    if not player_name:
        return jsonify({'error': '缺少角色名'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权访问此角色'}), 403

    conn = sqlite3.connect('chat.db')
    conn.row_factory = sqlite3.Row
    try:
        c = conn.cursor()
        c.execute('''
            SELECT ps.*, 
                   pv.level, pv.current_exp_per_minute,
                   v.name as vehicle_name, v.icon, v.exp_per_minute as base_exp
            FROM parking_spots ps
            LEFT JOIN player_vehicles pv ON ps.vehicle_instance_id = pv.id
            LEFT JOIN parking_vehicles v ON pv.vehicle_id = v.id
            WHERE ps.owner_name = ?
            ORDER BY ps.spot_index
        ''', (player_name,))
        rows = c.fetchall()
        spots = []
        now = int(time.time())
        parking_cfg = CONFIG.get('parking', {})
        other_multiplier = parking_cfg.get('other_spot_multiplier', 2)
        rent_rate = parking_cfg.get('owner_rent_rate', 0.5)
        max_seconds = parking_cfg.get('max_parking_seconds', 86400)

        for row in rows:
            spot = dict(row)
            if spot['parked_by']:
                instance = get_vehicle_instance(spot['vehicle_instance_id'])
                if not instance:
                    clear_parking_spot(spot['owner_name'], spot['spot_index'])
                    spot['vehicle_name'] = None
                    spot['icon'] = None
                    spot['exp_per_minute'] = 0
                    spot['elapsed_minutes'] = 0
                    spot['pending_exp'] = 0
                    spot['pending_rent'] = 0
                else:
                    vehicle = get_vehicle_info(instance['vehicle_id'])
                    base_exp_per_hour = instance['current_exp_per_minute'] if instance['current_exp_per_minute'] else vehicle['exp_per_minute']
                    exp_per_minute = base_exp_per_hour / 60.0
                    elapsed_minutes = (now - spot['start_time']) / 60.0
                    elapsed_minutes = min(elapsed_minutes, max_seconds / 60.0)

                    if spot['parked_by'] != spot['owner_name']:
                        multiplier = other_multiplier
                    else:
                        multiplier = 1

                    pending_exp = int(exp_per_minute * elapsed_minutes * multiplier) if vehicle else 0

                    # 租金：只有其他车辆且未收过租金时，才计算一次性租金
                    if spot['parked_by'] != spot['owner_name'] and spot.get('last_rent_time') is None:
                        pending_rent = int(pending_exp * rent_rate)
                    else:
                        pending_rent = 0

                    spot.update({
                        'vehicle_name': vehicle['name'],
                        'icon': vehicle['icon'],
                        'exp_per_minute': base_exp_per_hour,
                        'elapsed_minutes': round(elapsed_minutes, 2),
                        'pending_exp': pending_exp,
                        'pending_rent': pending_rent,
                        'multiplier': multiplier,
                    })
            else:
                spot['vehicle_name'] = None
                spot['icon'] = None
                spot['elapsed_minutes'] = 0
                spot['pending_exp'] = 0
                spot['pending_rent'] = 0
            spots.append(spot)
        return jsonify({'spots': spots})
    finally:
        conn.close()

@parking_bp.route('/other_spots', methods=['GET'])
def other_spots():
    player_name = request.args.get('name')
    if not player_name:
        return jsonify({'error': '缺少角色名'}), 400
    conn = sqlite3.connect('chat.db')
    conn.row_factory = sqlite3.Row
    try:
        c = conn.cursor()
        c.execute('''
            SELECT owner_name, spot_index
            FROM parking_spots
            WHERE parked_by IS NULL AND owner_name != ?
            ORDER BY owner_name, spot_index
        ''', (player_name,))
        rows = c.fetchall()
        spots = [{'owner_name': r['owner_name'], 'spot_index': r['spot_index']} for r in rows]
        return jsonify({'spots': spots})
    finally:
        conn.close()

@parking_bp.route('/park', methods=['POST'])
def park():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    player_name = data.get('player_name')
    target_owner = data.get('target_owner')
    spot_index = data.get('spot_index')
    instance_id = data.get('instance_id')
    if not player_name or not target_owner or spot_index is None or not instance_id:
        return jsonify({'error': '参数不足'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403

    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT vehicle_id FROM player_vehicles WHERE player_name = ? AND id = ?', (player_name, instance_id))
        row = c.fetchone()
        if not row:
            return jsonify({'error': '车辆实例不存在'}), 400
        target_spot = get_parking_spot(target_owner, spot_index)
        if not target_spot:
            return jsonify({'error': '车位不存在'}), 400
        if target_spot['parked_by'] is not None:
            return jsonify({'error': '该车位已被占用'}), 400
        c.execute('SELECT 1 FROM parking_spots WHERE vehicle_instance_id = ? AND parked_by IS NOT NULL', (instance_id,))
        if c.fetchone():
            return jsonify({'error': '这辆车已经在某个车位停放，请先取回'}), 400
        now = int(time.time())
        update_parking_spot(target_owner, spot_index, player_name, instance_id, now)
        return jsonify({'success': True, 'message': f'已将车辆停放在 {target_owner} 的车位 {spot_index}'})
    finally:
        conn.close()

@parking_bp.route('/claim', methods=['POST'])
def claim_exp():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    player_name = data.get('player_name')
    spot_owner = data.get('spot_owner')
    spot_index = data.get('spot_index')
    if not player_name or not spot_owner or spot_index is None:
        return jsonify({'error': '参数不足'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403

    spot = get_parking_spot(spot_owner, spot_index)
    if not spot or spot['parked_by'] != player_name:
        return jsonify({'error': '车辆不存在或已被取走'}), 400
    instance = get_vehicle_instance(spot['vehicle_instance_id'])
    if not instance:
        clear_parking_spot(spot_owner, spot_index)
        return jsonify({'error': '车辆实例数据异常，已自动清理'}), 400
    vehicle = get_vehicle_info(instance['vehicle_id'])
    hourly_exp = instance['current_exp_per_minute'] if instance['current_exp_per_minute'] else vehicle['exp_per_minute']
    actual_exp_per_minute = hourly_exp / 60.0

    now = int(time.time())
    elapsed_minutes = (now - spot['start_time']) / 60.0
    min_minutes = CONFIG.get('parking', {}).get('min_parking_minutes', 1)
    if elapsed_minutes < min_minutes:
        return jsonify({'error': f'停车不足{min_minutes}分钟，无法取回'}), 400

    max_seconds = CONFIG.get('parking', {}).get('max_parking_seconds', 86400)
    elapsed_minutes = min(elapsed_minutes, max_seconds / 60.0)

    other_multiplier = CONFIG.get('parking', {}).get('other_spot_multiplier', 2)
    multiplier = other_multiplier if spot_owner != player_name else 1
    exp_gain = int(actual_exp_per_minute * elapsed_minutes * multiplier)

    state = get_player_state(player_name)
    if not state:
        return jsonify({'error': '角色不存在'}), 404

    if exp_gain > 0:
        state = add_exp_and_gold(state, exp_gain, 0)
        save_player_state(player_name, state)
        msg = f'获得 {exp_gain} 经验'
    else:
        msg = f'取回车辆无经验'

    clear_parking_spot(spot_owner, spot_index)
    return jsonify({'success': True, 'message': msg, 'exp_gained': exp_gain})

@parking_bp.route('/remove', methods=['POST'])
def remove_vehicle():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    player_name = data.get('player_name')
    spot_owner = data.get('spot_owner')
    spot_index = data.get('spot_index')
    if not player_name or not spot_owner or spot_index is None:
        return jsonify({'error': '参数不足'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403
    if player_name != spot_owner:
        return jsonify({'error': '您不是该车位的主人，无权移走车辆'}), 403

    spot = get_parking_spot(spot_owner, spot_index)
    if not spot or spot['parked_by'] is None:
        return jsonify({'error': '该车位无车辆停放'}), 400
    if spot['parked_by'] == spot_owner:
        return jsonify({'error': '这是您自己的车辆，请使用取回功能'}), 400
    instance = get_vehicle_instance(spot['vehicle_instance_id'])
    if not instance:
        clear_parking_spot(spot_owner, spot_index)
        return jsonify({'error': '车辆实例数据异常，已自动清理'}), 400
    vehicle = get_vehicle_info(instance['vehicle_id'])
    hourly_exp = instance['current_exp_per_minute'] if instance['current_exp_per_minute'] else vehicle['exp_per_minute']
    actual_exp_per_minute = hourly_exp / 60.0

    now = int(time.time())
    elapsed_minutes = (now - spot['start_time']) / 60.0
    min_minutes = CONFIG.get('parking', {}).get('min_parking_minutes', 1)
    if elapsed_minutes < min_minutes:
        return jsonify({'error': f'停车不足{min_minutes}分钟，无法移走'}), 400

    max_seconds = CONFIG.get('parking', {}).get('max_parking_seconds', 86400)
    elapsed_minutes = min(elapsed_minutes, max_seconds / 60.0)

    other_multiplier = CONFIG.get('parking', {}).get('other_spot_multiplier', 2)
    total_exp = int(actual_exp_per_minute * elapsed_minutes * other_multiplier)
    owner_gain = total_exp // 2   # 移走车辆的车位主人获得一半经验
    if owner_gain <= 0:
        return jsonify({'error': '无经验可获取'}), 400

    state = get_player_state(spot_owner)
    if not state:
        return jsonify({'error': '角色不存在'}), 404

    state = add_exp_and_gold(state, owner_gain, 0)
    save_player_state(spot_owner, state)
    clear_parking_spot(spot_owner, spot_index)

    return jsonify({'success': True, 'message': f'移走车辆成功，获得 {owner_gain} 经验', 'exp_gained': owner_gain})

@parking_bp.route('/collect_rent', methods=['POST'])
def collect_rent():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    owner_name = data.get('owner_name')
    spot_index = data.get('spot_index')
    if not owner_name or spot_index is None:
        return jsonify({'error': '参数不足'}), 400
    if not _verify_character_owner(owner_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403

    spot = get_parking_spot(owner_name, spot_index)
    if not spot or spot['parked_by'] is None:
        return jsonify({'error': '该车位无车辆停放'}), 400
    if spot['parked_by'] == spot['owner_name']:
        return jsonify({'error': '这是您自己的车辆，不能收取租金'}), 400
    if spot.get('last_rent_time') is not None:
        return jsonify({'error': '该车辆租金已收取过，不能重复收取'}), 400

    instance = get_vehicle_instance(spot['vehicle_instance_id'])
    if not instance:
        return jsonify({'error': '车辆实例数据异常'}), 400
    vehicle = get_vehicle_info(instance['vehicle_id'])
    hourly_exp = instance['current_exp_per_minute'] if instance['current_exp_per_minute'] else vehicle['exp_per_minute']
    actual_exp_per_minute = hourly_exp / 60.0

    now = int(time.time())
    elapsed_minutes = (now - spot['start_time']) / 60.0
    min_minutes = CONFIG.get('parking', {}).get('min_parking_minutes', 1)
    if elapsed_minutes < min_minutes:
        return jsonify({'error': f'停车不足{min_minutes}分钟，无法收取租金'}), 400

    max_seconds = CONFIG.get('parking', {}).get('max_parking_seconds', 86400)
    elapsed_minutes = min(elapsed_minutes, max_seconds / 60.0)

    other_multiplier = CONFIG.get('parking', {}).get('other_spot_multiplier', 2)
    total_exp = int(actual_exp_per_minute * elapsed_minutes * other_multiplier)
    rent_rate = CONFIG.get('parking', {}).get('owner_rent_rate', 0.5)
    rent = int(total_exp * rent_rate)
    if rent <= 0:
        return jsonify({'error': '无可收取的租金'}), 400

    state = get_player_state(owner_name)
    if not state:
        return jsonify({'error': '角色不存在'}), 404

    state = add_exp_and_gold(state, rent, 0)
    save_player_state(owner_name, state)

    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('UPDATE parking_spots SET last_rent_time = ? WHERE owner_name = ? AND spot_index = ?',
                  (now, owner_name, spot_index))
        conn.commit()
    finally:
        conn.close()

    return jsonify({'success': True, 'message': f'收取 {rent} 经验', 'exp_gained': rent})

@parking_bp.route('/collect_all_rent', methods=['POST'])
def collect_all_rent():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    owner_name = data.get('owner_name')
    if not owner_name:
        return jsonify({'error': '缺少参数'}), 400
    if not _verify_character_owner(owner_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403

    conn = sqlite3.connect('chat.db')
    conn.row_factory = sqlite3.Row
    try:
        c = conn.cursor()
        c.execute('''
            SELECT * FROM parking_spots
            WHERE owner_name = ? AND parked_by IS NOT NULL AND parked_by != owner_name AND last_rent_time IS NULL
        ''', (owner_name,))
        rows = c.fetchall()
        total_rent = 0
        now = int(time.time())
        parking_cfg = CONFIG.get('parking', {})
        other_multiplier = parking_cfg.get('other_spot_multiplier', 2)
        rent_rate = parking_cfg.get('owner_rent_rate', 0.5)
        min_minutes = parking_cfg.get('min_parking_minutes', 1)
        max_seconds = parking_cfg.get('max_parking_seconds', 86400)

        for row in rows:
            spot = dict(row)
            instance = get_vehicle_instance(spot['vehicle_instance_id'])
            if not instance:
                continue
            vehicle = get_vehicle_info(instance['vehicle_id'])
            hourly_exp = instance['current_exp_per_minute'] if instance['current_exp_per_minute'] else vehicle['exp_per_minute']
            actual_exp_per_minute = hourly_exp / 60.0

            elapsed_minutes = (now - spot['start_time']) / 60.0
            if elapsed_minutes < min_minutes:
                continue
            elapsed_minutes = min(elapsed_minutes, max_seconds / 60.0)

            total_exp = int(actual_exp_per_minute * elapsed_minutes * other_multiplier)
            rent = int(total_exp * rent_rate)
            if rent > 0:
                total_rent += rent
                c.execute('UPDATE parking_spots SET last_rent_time = ? WHERE owner_name = ? AND spot_index = ?',
                          (now, owner_name, spot['spot_index']))

        conn.commit()
        if total_rent > 0:
            state = get_player_state(owner_name)
            if state:
                state = add_exp_and_gold(state, total_rent, 0)
                save_player_state(owner_name, state)
                message = f'成功收取 {total_rent} 经验'
            else:
                message = '角色状态异常'
        else:
            message = '没有可收取的租金'
        return jsonify({'success': True, 'message': message, 'exp_gained': total_rent})
    finally:
        conn.close()

@parking_bp.route('/preview', methods=['POST'])
def preview_parking():
    data = request.json
    vehicle_id = data.get('vehicle_id')
    instance_id = data.get('instance_id')
    target_owner = data.get('target_owner')
    
    if instance_id:
        instance = get_vehicle_instance(instance_id)
        if not instance:
            return jsonify({'error': '车辆实例不存在'}), 400
        vehicle = get_vehicle_info(instance['vehicle_id'])
        exp_per_hour = instance.get('current_exp_per_minute', vehicle['exp_per_minute'])
    else:
        vehicle = get_vehicle_info(vehicle_id)
        if not vehicle:
            return jsonify({'error': '车辆不存在'}), 400
        exp_per_hour = vehicle['exp_per_minute']
    
    is_other = (target_owner != 'self')
    multiplier = CONFIG.get('parking', {}).get('other_spot_multiplier', 2) if is_other else 1
    final_exp_per_hour = exp_per_hour * multiplier
    
    # 不再有每日上限
    daily_cap = 10**12
    return jsonify({
        'hourly_exp': final_exp_per_hour,
        'daily_exp': final_exp_per_hour * 24,
        'daily_cap': daily_cap,
        'multiplier': multiplier,
        'vehicle_name': vehicle['name']
    })

@parking_bp.route('/upgrade', methods=['POST'])
def upgrade_vehicle():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    data = request.json
    player_name = data.get('player_name')
    instance_id = data.get('instance_id')
    if not player_name or not instance_id:
        return jsonify({'error': '参数不足'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权操作此角色'}), 403

    # 检查车辆是否正在停放
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT 1 FROM parking_spots WHERE vehicle_instance_id = ? AND parked_by IS NOT NULL', (instance_id,))
        if c.fetchone():
            return jsonify({'error': '车辆正在停放中，请先取回再升级'}), 400
    finally:
        conn.close()

    state = get_player_state(player_name)
    if not state:
        return jsonify({'error': '角色不存在'}), 404
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT level, current_exp_per_minute, vehicle_id FROM player_vehicles WHERE player_name = ? AND id = ?',
                  (player_name, instance_id))
        row = c.fetchone()
        if not row:
            return jsonify({'error': '车辆实例不存在'}), 400
        current_level = row[0] if row[0] else 1
        if current_level >= 20:
            return jsonify({'error': '车辆已达到最高等级20级，无法继续升级'}), 400
        vehicle_id = row[2]
        vehicle = get_vehicle_info(vehicle_id)
        base_exp_per_minute = vehicle['exp_per_minute']
        upgrade_cost = vehicle['price']

        if state['player']['gold'] < upgrade_cost:
            return jsonify({'error': f'金币不足，需要 {upgrade_cost} 金币'}), 400

        state['player']['gold'] -= upgrade_cost
        save_player_state(player_name, state)

        new_level = current_level + 1
        upgrade_multiplier = CONFIG.get('parking', {}).get('upgrade_exp_multiplier', 1.0)
        new_exp_per_minute = base_exp_per_minute * (1 + (new_level - 1) * upgrade_multiplier)
        c.execute('UPDATE player_vehicles SET level = ?, current_exp_per_minute = ? WHERE player_name = ? AND id = ?',
                  (new_level, new_exp_per_minute, player_name, instance_id))
        conn.commit()
        
        return jsonify({
            'success': True, 
            'message': f'车辆升级成功！当前 Lv.{new_level}，收益 {new_exp_per_minute} 经验/小时',
            'new_level': new_level,
            'new_exp_per_minute': new_exp_per_minute
        })
    except Exception as e:
        conn.rollback()
        return jsonify({'error': f'升级失败: {str(e)}'}), 500
    finally:
        conn.close()


@parking_bp.route('/my_parked_vehicles', methods=['GET'])
def my_parked_vehicles():
    user_id = _get_user_from_request(request)
    if not user_id:
        return jsonify({'error': '未登录'}), 401
    player_name = request.args.get('name')
    if not player_name:
        return jsonify({'error': '缺少角色名'}), 400
    if not _verify_character_owner(player_name, user_id):
        return jsonify({'error': '无权访问此角色'}), 403

    conn = sqlite3.connect('chat.db')
    conn.row_factory = sqlite3.Row
    try:
        c = conn.cursor()
        c.execute('''
            SELECT owner_name, spot_index, vehicle_instance_id
            FROM parking_spots
            WHERE parked_by = ?
        ''', (player_name,))
        rows = c.fetchall()
        parkings = []
        for row in rows:
            spot = dict(row)
            instance = get_vehicle_instance(spot['vehicle_instance_id'])
            if instance:
                vehicle = get_vehicle_info(instance['vehicle_id'])
                spot['vehicle_name'] = vehicle['name']
                spot['icon'] = vehicle['icon']
            parkings.append(spot)
        return jsonify({'parkings': parkings})
    finally:
        conn.close()

# ========== 后台自动清理任务 ==========
def auto_cleanup_parking():
    while True:
        interval = CONFIG.get('parking', {}).get('auto_cleanup_interval_seconds', 300)
        time.sleep(interval)
        conn = sqlite3.connect('chat.db')
        try:
            c = conn.cursor()
            now = int(time.time())
            timeout = CONFIG.get('parking', {}).get('max_parking_seconds', 86400)
            c.execute('''
                SELECT owner_name, spot_index, parked_by, vehicle_instance_id, start_time
                FROM parking_spots
                WHERE parked_by IS NOT NULL AND start_time <= ?
            ''', (now - timeout,))
            expired_spots = c.fetchall()
            other_multiplier = CONFIG.get('parking', {}).get('other_spot_multiplier', 2)
            for spot in expired_spots:
                owner_name, spot_index, parked_by, vehicle_instance_id, start_time = spot
                instance = get_vehicle_instance(vehicle_instance_id)
                if instance:
                    vehicle = get_vehicle_info(instance['vehicle_id'])
                    hourly_exp = instance['current_exp_per_minute'] if instance['current_exp_per_minute'] else vehicle['exp_per_minute']
                    actual_exp_per_minute = hourly_exp / 60.0
                    elapsed_minutes = (now - start_time) / 60.0
                    multiplier = other_multiplier if parked_by != owner_name else 1
                    exp_gain = int(actual_exp_per_minute * elapsed_minutes * multiplier)
                    if exp_gain > 0:
                        state = get_player_state(parked_by)
                        if state:
                            state = add_exp_and_gold(state, exp_gain, 0)
                            save_player_state(parked_by, state)
                clear_parking_spot(owner_name, spot_index)
            conn.commit()
        except Exception as e:
            print(f"自动清理停车异常: {e}")
        finally:
            conn.close()

# ========== 逻辑函数（供 socket 调用） ==========
def buy_vehicle_logic(player_name, vehicle_id):
    state = get_player_state(player_name)
    if not state:
        return False, '角色不存在', None
    vehicle = get_vehicle_info(vehicle_id)
    if not vehicle:
        return False, '车辆不存在', None
    if state['player']['gold'] < vehicle['price']:
        return False, f'金币不足，需要{vehicle["price"]}金币', None
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        state['player']['gold'] -= vehicle['price']
        if 'userId' not in state:
            c.execute('SELECT user_id FROM characters WHERE name = ?', (player_name,))
            row = c.fetchone()
            if row and row[0]:
                state['userId'] = row[0]
            else:
                state['userId'] = 0
        save_player_state(player_name, state)
        c.execute('''
            INSERT INTO player_vehicles (player_name, vehicle_id, is_selected, level, current_exp_per_minute)
            VALUES (?, ?, ?, ?, ?)
        ''', (player_name, vehicle_id, 0, 1, vehicle['exp_per_minute']))
        # 创建车位
        c.execute('SELECT COUNT(*) FROM parking_spots WHERE owner_name = ?', (player_name,))
        if c.fetchone()[0] == 0:
            ensure_parking_spots(player_name)
        conn.commit()
        return True, f'成功购买 {vehicle["name"]}', {'vehicle_id': vehicle_id, 'name': vehicle['name']}
    except Exception as e:
        conn.rollback()
        return False, f'购买失败: {str(e)}', None
    finally:
        conn.close()

def upgrade_vehicle_logic(player_name, instance_id):
    state = get_player_state(player_name)
    if not state:
        return False, '角色不存在', None
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        # 检查是否停放
        c.execute('SELECT 1 FROM parking_spots WHERE vehicle_instance_id = ? AND parked_by IS NOT NULL', (instance_id,))
        if c.fetchone():
            return False, '车辆正在停放中，请先取回再升级', None

        c.execute('SELECT level, current_exp_per_minute, vehicle_id FROM player_vehicles WHERE player_name = ? AND id = ?', 
                  (player_name, instance_id))
        row = c.fetchone()
        if not row:
            return False, '车辆实例不存在', None
        current_level = row[0] if row[0] else 1
        if current_level >= 20:
            return False, '车辆已达到最高等级20级，无法继续升级', None
        vehicle_id = row[2]
        vehicle = get_vehicle_info(vehicle_id)
        base_exp_per_minute = vehicle['exp_per_minute']
        upgrade_cost = vehicle['price']
        if state['player']['gold'] < upgrade_cost:
            return False, f'金币不足，需要 {upgrade_cost} 金币', None
        state['player']['gold'] -= upgrade_cost
        save_player_state(player_name, state)
        new_level = current_level + 1
        upgrade_multiplier = CONFIG.get('parking', {}).get('upgrade_exp_multiplier', 1.0)
        new_exp_per_minute = base_exp_per_minute * (1 + (new_level - 1) * upgrade_multiplier)
        c.execute('''
            UPDATE player_vehicles 
            SET level = ?, current_exp_per_minute = ? 
            WHERE player_name = ? AND id = ?
        ''', (new_level, new_exp_per_minute, player_name, instance_id))
        conn.commit()
        return True, f'车辆升级成功！当前 Lv.{new_level}，收益 {new_exp_per_minute} 经验/小时', {
            'new_level': new_level,
            'new_exp_per_minute': new_exp_per_minute
        }
    except Exception as e:
        conn.rollback()
        return False, f'升级失败: {str(e)}', None
    finally:
        conn.close()

def park_vehicle_logic(player_name, target_owner, spot_index, instance_id):
    conn = sqlite3.connect('chat.db')
    try:
        c = conn.cursor()
        c.execute('SELECT vehicle_id FROM player_vehicles WHERE player_name = ? AND id = ?', (player_name, instance_id))
        row = c.fetchone()
        if not row:
            return False, '车辆实例不存在', None
        target_spot = get_parking_spot(target_owner, spot_index)
        if not target_spot:
            return False, '车位不存在', None
        if target_spot['parked_by'] is not None:
            return False, '该车位已被占用', None
        c.execute('SELECT 1 FROM parking_spots WHERE vehicle_instance_id = ? AND parked_by IS NOT NULL', (instance_id,))
        if c.fetchone():
            return False, '这辆车已经在某个车位停放，请先取回', None
        now = int(time.time())
        update_parking_spot(target_owner, spot_index, player_name, instance_id, now)
        conn.commit()
        return True, f'已将车辆停放在 {target_owner} 的车位 {spot_index}', None
    except Exception as e:
        conn.rollback()
        return False, f'停放失败: {str(e)}', None
    finally:
        conn.close()

def claim_exp_logic(player_name, spot_owner, spot_index):
    spot = get_parking_spot(spot_owner, spot_index)
    if not spot or spot['parked_by'] != player_name:
        return False, '车辆不存在或已被取走', None
    instance = get_vehicle_instance(spot['vehicle_instance_id'])
    if not instance:
        clear_parking_spot(spot_owner, spot_index)
        return False, '车辆实例数据异常，已自动清理', None
    vehicle = get_vehicle_info(instance['vehicle_id'])
    hourly_exp = instance['current_exp_per_minute'] if instance['current_exp_per_minute'] else vehicle['exp_per_minute']
    actual_exp_per_minute = hourly_exp / 60.0
    
    now = int(time.time())
    elapsed_minutes = (now - spot['start_time']) / 60.0
    min_minutes = CONFIG.get('parking', {}).get('min_parking_minutes', 1)
    if elapsed_minutes < min_minutes:
        return False, f'停车不足{min_minutes}分钟，无法取回', None
    max_seconds = CONFIG.get('parking', {}).get('max_parking_seconds', 86400)
    elapsed_minutes = min(elapsed_minutes, max_seconds / 60.0)

    other_multiplier = CONFIG.get('parking', {}).get('other_spot_multiplier', 2)
    multiplier = other_multiplier if spot_owner != player_name else 1
    exp_gain = int(actual_exp_per_minute * elapsed_minutes * multiplier)
    
    state = get_player_state(player_name)
    if not state:
        return False, '角色不存在', None
    
    if exp_gain > 0:
        state = add_exp_and_gold(state, exp_gain, 0)
        save_player_state(player_name, state)
        msg = f'获得 {exp_gain} 经验'
    else:
        msg = f'取回车辆无经验'
    
    clear_parking_spot(spot_owner, spot_index)
    return True, msg, {'exp_gained': exp_gain}