/**
 * 宠物王国：传说 - 核心逻辑 (Game Engine) v21.3 (离线打包与资源修复版)
 * 更新日志：
 * 1. [Fix] 修复了“前冠军”和“炎斗士”任务完成后无法存档（导致重复接取）的Bug。
 * 2. [Input] 新增空格键（Space）推进对话的功能。
 * 3. [Map] 新增鼠标悬停地图时的网格预览光标，提升操作精准度。
 * 4. [Pack] 清理离线包中不存在的预加载资源，修复默认地图贴图回退。
 */

// --- 全局调试 ---
console.log("Game Engine v21.3 Loading...");

// --- 工具函数 ---
const $ = id => document.getElementById(id);
const rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const sleep = ms => new Promise(r => setTimeout(r, ms));

// 安全更新 DOM 的辅助函数
const setTxt = (id, txt) => { 
    const el = $(id); 
    if(el) el.innerText = txt; 
};
const setWidth = (id, pct) => { 
    const el = $(id); 
    if(el) el.style.width = `${pct}%`; 
};
const setClass = (id, cls) => { 
    const el = $(id); 
    if(el) el.className = cls; 
};

function toast(msg) { 
    const el = $('toast-msg'); 
    if(el) { 
        el.innerText = msg; 
        const p = el.parentElement; 
        p.style.opacity = '1'; 
        p.style.top = '110px'; 
        setTimeout(() => { 
            p.style.opacity = '0'; 
            p.style.top = '90px'; 
        }, 2000); 
    } 
}

// --- 8 属性克制矩阵 (攻击方 -> 防守方) ---
const TYPE_MATRIX = {
    'gold':   { 'wood': 1.5, 'fire': 0.5, 'water': 1.0, 'earth': 1.0, 'gold': 0.5, 'wind': 1.0, 'thunder': 0.5, 'ghost': 1.0 },
    'wood':   { 'earth': 1.5, 'gold': 0.5, 'water': 1.0, 'fire': 0.5, 'wood': 0.5, 'wind': 0.5, 'thunder': 1.0, 'ghost': 1.0 },
    'water':  { 'fire': 1.5, 'earth': 0.5, 'wood': 1.0, 'gold': 1.0, 'water': 0.5, 'wind': 1.0, 'thunder': 0.5, 'ghost': 1.0 },
    'fire':   { 'gold': 1.5, 'water': 0.5, 'wood': 1.0, 'earth': 1.0, 'fire': 0.5, 'wind': 1.0, 'thunder': 1.0, 'ghost': 1.0 },
    'earth':  { 'water': 1.5, 'wood': 0.5, 'fire': 1.0, 'gold': 1.0, 'earth': 0.5, 'wind': 0.5, 'thunder': 1.5, 'ghost': 1.0 },
    'wind':   { 'wood': 1.5, 'earth': 1.5, 'fire': 1.0, 'water': 1.0, 'gold': 0.5, 'wind': 0.5, 'thunder': 1.0, 'ghost': 0.5 },
    'thunder':{ 'water': 1.5, 'gold': 1.5, 'earth': 0.5, 'wood': 1.0, 'fire': 1.0, 'wind': 1.0, 'thunder': 0.5, 'ghost': 1.0 },
    'ghost':  { 'ghost': 2.0, 'wind': 1.0, 'earth': 1.0, 'fire': 1.0, 'water': 1.0, 'wood': 1.0, 'gold': 1.0, 'thunder': 1.0 }
};

const TYPE_NAMES = {
    wood: '木', fire: '火', water: '水', gold: '金', earth: '土',
    wind: '风', thunder: '雷', ghost: '鬼'
};

function getPetImage(id) { 
    return `
    <div class="relative w-full h-full flex items-center justify-center group overflow-hidden rounded-xl bg-black/10">
        <img src="./images/${id}.png" loading="lazy" class="pet-img relative z-10 w-full h-full object-contain transition-opacity duration-300" onload="this.style.opacity=1" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex'">
        <div class="pet-img-placeholder hidden flex-col items-center justify-center text-gray-500 text-center p-2 w-full h-full absolute inset-0 z-0">
            <span class="text-3xl mb-1 opacity-50">🐾</span>
            <span class="text-[9px] break-all font-mono opacity-70 font-bold">${id}</span>
        </div>
    </div>`; 
}

// --- 资源管理器 ---
const imgManager = {
    cache: {},
    load(src) { return this.loadAsync(src); },
    loadAsync(src) {
        return new Promise((resolve) => {
            if (this.cache[src] !== undefined) return resolve(this.cache[src]);
            const img = new Image();
            img.src = `./images/${src}.png`;
            img.onload = () => { this.cache[src] = img; resolve(img); };
            img.onerror = () => { this.cache[src] = null; resolve(null); };
        });
    },
    get(src) { return this.cache[src]; },
    async preloadAll(onProgress) {
        const assets = [];
        if (typeof SPECIES !== 'undefined') Object.keys(SPECIES).forEach(k => assets.push(k));
        ['summoner', 'chest_closed', 'chest_open', 'icon', 'logo'].forEach(k => assets.push(k));
        ['npc_milo', 'npc_lily', 'npc_flame_warrior', 'npc_angler', 'npc_weather_girl', 'npc_gravekeeper', 'npc_champion_rival', 'npc_professor', 'npc_passerby_a', 'npc_passerby_b', 'npc_passerby_c', 'npc_cunzhang', 'npc_merchant'].forEach(k => assets.push(k));
        ['tile_wall', 'tile_exit', 'tile_meadow', 'tile_volcano', 'tile_beach', 'tile_sky', 'tile_graveyard', 'tile_arena'].forEach(k => assets.push(k));
        ['item_potion', 'item_ball', 'item_ring_silver', 'item_ring_gold', 'item_ring_overlord'].forEach(k => assets.push(k));
        ['meadow', 'volcano', 'beach', 'sky', 'graveyard', 'arena'].forEach(theme => {
            ['tree', 'rock', 'house', 'plant'].forEach(type => { assets.push(`obs_${theme}_${type}`); });
        });

        const CHUNK_SIZE = 10; let loaded = 0; const total = assets.length;
        for (let i = 0; i < total; i += CHUNK_SIZE) {
            const chunk = assets.slice(i, i + CHUNK_SIZE);
            await Promise.all(chunk.map(src => this.loadAsync(src)));
            loaded += chunk.length;
            if (onProgress) onProgress(Math.min(100, Math.floor(loaded / total * 100)));
            await sleep(5); 
        }
    }
};

const store = { 
    gold: 100, pets: [], activeIdx: 0, 
    inventory: { potion: 3, ball: 3, guide_book: 0, xp_potion: 0 }, 
    unlockedAreas: ['meadow'], pokedex: [], storyFlags: {}, unlockedRings: [], team: [], activeQuestId: null,
    arenaCooldowns: {} 
};

const router = {
    go(view) {
        if (typeof battle !== 'undefined' && battle.active && view !== 'battle') return toast('战斗中无法脱离！');
        document.querySelectorAll('[id^="view-"]').forEach(el => el.classList.add('hidden'));
        
        const targetEl = $(`view-${view}`);
        if(targetEl) targetEl.classList.remove('hidden');
        
        const immersiveViews = ['start', 'exploration', 'battle'];
        if (immersiveViews.includes(view)) { 
            if(view === 'start' && window.story) story.end(); 
            $('sidebar').classList.add('hidden'); $('top-bar').classList.add('hidden'); 
        } else { $('sidebar').classList.remove('hidden'); $('top-bar').classList.remove('hidden'); }
        
        document.querySelectorAll('.nav-btn').forEach(btn => btn.classList.remove('active'));
        const navBtn = $(`nav-${view}`);
        if(navBtn) navBtn.classList.add('active');
        
        if (view === 'home') game.renderHome();
        if (view === 'dex') game.renderDex();
        if (view === 'map') game.renderMap();
        if (view === 'pokedex') game.renderPokedex();
        if (view === 'shop') game.renderShop();
        if (view === 'menu') game.renderMenu();
        if (view === 'arena') game.renderArena(); 
    }
};

const story = {
    queue: [], active: false, npcMap: { '博士': 'npc_professor', '系统': 'icon_system', '旁白': null },
    start(scenarioId) { if (!SCENARIOS[scenarioId]) return; this.queue = [...SCENARIOS[scenarioId]]; this.active = true; $('dialogue-overlay').classList.remove('hidden'); this.next(); },
    next() {
        $('dialogue-choices').innerHTML = ''; $('dialogue-choices').classList.add('hidden'); $('dialogue-next-btn').classList.remove('hidden');
        if (this.queue.length === 0) { this.end(); return; }
        const line = this.queue.shift();
        
        if (line.effect === 'give_gold') { 
            store.gold += 100; 
            game.updateHud(); 
            toast('获得 100 金币!'); 
            // 修复：在这里添加任务完成标记，防止竞技场前冠军等直接给奖励的任务无限重复
            if (store.activeQuestId) {
                store.storyFlags[store.activeQuestId + '_done'] = true;
                game.save();
            }
        }
        if (line.effect === 'give_guide') { store.inventory.guide_book = 1; toast('获得重要道具：世界旅途指南！'); game.save(); }
        if (line.effect === 'finish_chief_talk') { store.storyFlags['intro_chief_talked'] = true; game.save(); }

        setTxt('dialogue-speaker', line.speaker);
        setTxt('dialogue-text', line.text);
        
        let imgId = null;
        if (line.speaker === '召唤师' || line.speaker === '我') imgId = 'summoner';
        else if (this.npcMap.hasOwnProperty(line.speaker)) imgId = this.npcMap[line.speaker];
        else if (line.speaker === '精灵' || (game.getPet() && line.speaker === game.getPet().name)) { const p = game.getPet(); if(p) imgId = p.id; }
        else { const currentNpc = mapEngine.layout ? mapEngine.layout.npcs.find(n => n.name === line.speaker) : null; if (currentNpc) imgId = currentNpc.sprite; }
        
        const charContainer = $('dialogue-char-left-container');
        if (imgId && charContainer) { 
            const charImg = $('dialogue-char-left');
            if(charImg) charImg.src = `./images/${imgId}.png`; 
            charContainer.classList.remove('hidden'); 
        } else if (charContainer) { 
            charContainer.classList.add('hidden'); 
        }
        
        if (line.choices) {
            $('dialogue-next-btn').classList.add('hidden');
            const choicesEl = $('dialogue-choices'); 
            if(choicesEl) {
                choicesEl.innerHTML = ''; choicesEl.classList.remove('hidden');
                line.choices.forEach(choice => {
                    const btn = document.createElement('button'); btn.className = `dialogue-btn ${choice.text.includes('拒绝') ? 'reject' : ''}`; btn.innerText = choice.text;
                    btn.onclick = () => {
                         // 处理消耗类选项
                         if(choice.text.includes('消耗')) {
                            if (store.inventory.potion > 0) { 
                                store.inventory.potion--; 
                                game.updateHud(); 
                                if(store.activeQuestId) {
                                    store.storyFlags[store.activeQuestId + '_done'] = true; 
                                    game.save();
                                }
                                this.start(choice.next); 
                            } else toast('道具不足！');
                         } else if (choice.text.includes('给') && choice.text.includes('捕兽网')) {
                             if (store.inventory.ball > 0) { 
                                 store.inventory.ball--; 
                                 game.updateHud(); 
                                 if(store.activeQuestId) {
                                     store.storyFlags[store.activeQuestId + '_done'] = true;
                                     game.save();
                                 }
                                 this.start(choice.next); 
                             } else toast('道具不足！');
                         } else if (choice.text.includes('给') && choice.text.includes('伤药')) { // 修复：增加对伤药(炎斗士任务)的判断
                             if (store.inventory.potion > 0) { 
                                 store.inventory.potion--; 
                                 game.updateHud(); 
                                 if(store.activeQuestId) {
                                     store.storyFlags[store.activeQuestId + '_done'] = true;
                                     game.save();
                                 }
                                 this.start(choice.next); 
                             } else toast('道具不足！');
                         } else if (choice.text.includes('捐赠') || choice.text.includes('金币')) {
                            if(store.gold >= 50) { 
                                store.gold -= 50; // 修复：捐赠应该扣钱
                                game.updateHud();
                                if(store.activeQuestId) {
                                    store.storyFlags[store.activeQuestId + '_done'] = true;
                                    game.save();
                                }
                                this.start(choice.next); 
                            } else toast('金币不足！');
                         } else {
                            if (choice.next && choice.next.includes('correct') && store.activeQuestId) {
                                store.storyFlags[store.activeQuestId + '_done'] = true;
                                game.save();
                            }
                            this.start(choice.next);
                         }
                    }; 
                    choicesEl.appendChild(btn);
                });
            }
        }
    },
    end() { this.active = false; $('dialogue-overlay').classList.add('hidden'); mapEngine.render(); }
};

const mapEngine = {
    canvas: null, ctx: null, tileSize: 24, currentArea: null, layout: null, player: { x: 0, y: 0 }, active: false,
    collisionMap: [], 
    hoverPos: { x: -1, y: -1 }, // 新增：鼠标悬停位置
    renderMetrics: { scale: 1, offX: 0, offY: 0 }, // 新增：渲染参数，用于鼠标定位
    ASSET_CONFIG: { 
        5: { size: 3, name: 'tree', color: '#059669' }, 
        7: { size: 4, name: 'house', color: '#7c3aed' }, 
        6: { size: 2, name: 'rock', color: '#57534e' }, 
        8: { size: 1, name: 'plant', color: '#10b981' }, 
        9: { size: 1, name: 'wall', color: '#1f2937' } 
    },

    init() {
        this.canvas = $('exploration-canvas'); 
        if(!this.canvas) return;
        this.ctx = this.canvas.getContext('2d');
        this.ctx.imageSmoothingEnabled = false; 
        
        window.addEventListener('keydown', (e) => { 
            // 空格键推进剧情
            if (story.active) {
                if (e.code === 'Space' || e.key === ' ') {
                    e.preventDefault(); // 防止滚动页面
                    story.next();
                }
                return; 
            }

            if (!this.active) return; 
            if (['ArrowUp','w'].includes(e.key)) this.move(0, -1); 
            if (['ArrowDown','s'].includes(e.key)) this.move(0, 1); 
            if (['ArrowLeft','a'].includes(e.key)) this.move(-1, 0); 
            if (['ArrowRight','d'].includes(e.key)) this.move(1, 0); 
        });
        
        // 新增：鼠标移动预览
        this.canvas.addEventListener('mousemove', (e) => {
            if (!this.active || story.active || !this.layout) return;
            const rect = this.canvas.getBoundingClientRect();
            
            // 逆向计算网格坐标
            // 坐标 = (鼠标坐标 - Canvas偏移 - 居中偏移) / 缩放 / 格子大小
            const mouseX = (e.clientX - rect.left) * (this.canvas.width / rect.width);
            const mouseY = (e.clientY - rect.top) * (this.canvas.height / rect.height);
            
            const rawX = (mouseX - this.renderMetrics.offX) / this.renderMetrics.scale;
            const rawY = (mouseY - this.renderMetrics.offY) / this.renderMetrics.scale;
            
            const gridX = Math.floor(rawX / this.tileSize);
            const gridY = Math.floor(rawY / this.tileSize);
            
            if (gridX >= 0 && gridX < this.layout.width && gridY >= 0 && gridY < this.layout.height) {
                if (this.hoverPos.x !== gridX || this.hoverPos.y !== gridY) {
                    this.hoverPos = { x: gridX, y: gridY };
                    this.render();
                }
            } else {
                this.hoverPos = { x: -1, y: -1 };
                this.render();
            }
        });

        this.canvas.addEventListener('click', (e) => {
            if (!this.active || story.active) return;
            
            // 如果鼠标正好在格子内，根据格子相对于玩家的方向移动
            if (this.hoverPos.x !== -1) {
                const dx = this.hoverPos.x - this.player.x;
                const dy = this.hoverPos.y - this.player.y;
                
                // 简单的寻路：每次点击只走一步，优先走距离更远的方向
                if (Math.abs(dx) > Math.abs(dy)) {
                    this.move(dx > 0 ? 1 : -1, 0);
                } else {
                    this.move(0, dy > 0 ? 1 : -1);
                }
                return;
            }

            // 备用逻辑：根据屏幕中心点判断
            const rect = this.canvas.getBoundingClientRect();
            const cx = rect.width / 2;
            const cy = rect.height / 2;
            const dx = e.clientX - rect.left - cx;
            const dy = e.clientY - rect.top - cy;
            
            if(Math.abs(dx) > Math.abs(dy)) {
                this.move(dx > 0 ? 1 : -1, 0);
            } else {
                this.move(0, dy > 0 ? 1 : -1);
            }
        });
        
        window.addEventListener('resize', () => { if(this.active) this.fitCanvasToScreen(); });
    },
    
    fitCanvasToScreen() {
        if(!this.layout) return;
        const parent = this.canvas.parentElement; 
        const rect = parent.getBoundingClientRect();
        
        const dpr = window.devicePixelRatio || 1;
        this.canvas.width = rect.width * dpr;
        this.canvas.height = rect.height * dpr;
        
        this.canvas.style.width = `${rect.width}px`;
        this.canvas.style.height = `${rect.height}px`;

        const mapW = this.layout.width * this.tileSize;
        const mapH = this.layout.height * this.tileSize;
        
        const scale = Math.min(this.canvas.width / mapW, this.canvas.height / mapH);
        const offsetX = (this.canvas.width - mapW * scale) / 2;
        const offsetY = (this.canvas.height - mapH * scale) / 2;

        // 保存渲染参数供鼠标事件使用
        this.renderMetrics = { scale, offX: offsetX, offY: offsetY };

        this.ctx.setTransform(scale, 0, 0, scale, offsetX, offsetY);
        this.ctx.imageSmoothingEnabled = false; 
        
        this.render();
    },

    resume() { this.active = true; router.go('exploration'); setTimeout(()=>this.fitCanvasToScreen(), 50); },
    
    initCollisionMap() {
        this.collisionMap = Array(this.layout.height).fill().map(() => Array(this.layout.width).fill(0));
        for(let y = 0; y < this.layout.height; y++) {
            for(let x = 0; x < this.layout.width; x++) {
                const tile = this.layout.tiles[y][x];
                if (this.ASSET_CONFIG[tile]) {
                    const size = this.ASSET_CONFIG[tile].size;
                    for(let dy=0; dy<size; dy++) for(let dx=0; dx<size; dx++) {
                        if(y+dy < this.layout.height && x+dx < this.layout.width) this.collisionMap[y+dy][x+dx] = 1;
                    }
                }
            }
        }
    },

    start(area) {
        this.currentArea = area; this.layout = MAP_LAYOUTS[area.mapKey] || MAP_LAYOUTS['default'];
        this.initCollisionMap();
        this.hoverPos = {x: -1, y: -1}; // 重置光标
        
        let startX = 1, startY = 18;
        if(this.collisionMap[startY][startX]) {
             for(let y=18; y>0; y--) for(let x=1; x<30; x++) {
                 if(!this.collisionMap[y][x]) { startX=x; startY=y; break; }
             }
        }
        this.player.x = startX; this.player.y = startY; 
        
        this.active = true; router.go('exploration'); 
        setTxt('explore-area-name', area.name);
        
        if (area.id === 'meadow' && !store.storyFlags['intro_chief_talked']) {
             setTimeout(() => toast('系统提示：村长就在入口处等你。'), 1000);
        }
        
        setTimeout(() => this.fitCanvasToScreen(), 100);
    },
    
    exit() { this.active = false; router.go('map'); },
    
    checkEncounter(x, y) {
        const neighbors = [[0,1],[0,-1],[1,0],[-1,0], [1,1], [1,-1], [-1,1], [-1,-1]];
        let nearDanger = false;
        
        for(let d of neighbors) {
            const nx = x + d[0];
            const ny = y + d[1];
            if(nx >= 0 && nx < this.layout.width && ny >= 0 && ny < this.layout.height) {
                const t = this.layout.tiles[ny][nx];
                if(t === 5 || t === 6) {
                    nearDanger = true;
                    break;
                }
            }
        }

        if (!nearDanger) return;

        if (Math.random() < 0.15) { 
            this.active = false; 
            toast('⚠️ 遭遇野生精灵！'); 
            setTimeout(() => battle.init(this.currentArea), 800); 
        }
    },

    move(dx, dy) { 
        const newX = this.player.x + dx; const newY = this.player.y + dy; 
        if (newX < 0 || newX >= this.layout.width || newY < 0 || newY >= this.layout.height) return; 
        if (this.collisionMap[newY][newX] === 1) return;
        
        const npc = this.layout.npcs.find(n => n.x === newX && n.y === newY);
        if(npc) {
            this.interactNpc(npc);
            return;
        }

        this.player.x = newX; this.player.y = newY; this.render(); 
        if (this.layout.tiles[newY][newX] === 2) { 
            game.showConfirm('确定要离开这个区域吗？', () => { this.exit(); }); 
            return; 
        }
        
        const chest = this.layout.chests.find(c => c.x === newX && c.y === newY && !c.opened);
        if(chest) {
            chest.opened = true;
            let valText = '';
            let typeName = '';
            
            if(chest.reward.type === 'gold') { 
                store.gold += chest.reward.val; 
                typeName = 'gold';
                valText = chest.reward.val;
            } else if(chest.reward.type === 'item') { 
                store.inventory[chest.reward.val]++; 
                typeName = chest.reward.val;
                valText = 1;
            }
            
            game.save();
            this.render();
            // 触发物品获得弹窗，而不是 Toast
            game.showRewardModal(typeName, valText);
        }

        this.checkEncounter(newX, newY);
    },
    
    interactNpc(npc) {
        if(npc.type === 'quest') {
            if(store.storyFlags[npc.questId+'_done']) {
                const chats = ['天气真不错啊。', '谢谢你之前的帮助！', '听说远方有更强大的精灵。', '要注意安全哦。', '我现在感觉好多了。'];
                const text = chats[Math.floor(Math.random() * chats.length)];
                story.queue = [{speaker: npc.name, text: text}];
            } else {
                store.activeQuestId = npc.questId; 
                story.start(npc.questId);
                return;
            }
        } else {
            if(npc.name === '村长' && !store.storyFlags['intro_chief_talked']) {
                story.start('chief_intro');
                return;
            }
            story.queue = [{speaker: npc.name, text: npc.dialog || "你好！"}];
        }
        story.active = true; $('dialogue-overlay').classList.remove('hidden'); story.next();
    },

    render() {
        if (!this.active) return;
        const ctx = this.ctx; const ts = this.tileSize;
        const bgKey = this.layout.assets.ground || 'tile_meadow';
        const bgImg = imgManager.get(bgKey);
        
        // 绘制地面
        for(let y=0; y<this.layout.height; y++) {
            for(let x=0; x<this.layout.width; x++) {
                if (bgImg) { ctx.drawImage(bgImg, x*ts, y*ts, ts, ts); } 
                else { ctx.fillStyle = this.currentArea.id === 'volcano' ? '#7f1d1d' : '#10b981'; ctx.fillRect(x*ts, y*ts, ts, ts); }
            }
        }

        // 绘制鼠标光标 (在地面之上，物体之下)
        if (this.hoverPos.x !== -1) {
            ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
            ctx.fillRect(this.hoverPos.x * ts, this.hoverPos.y * ts, ts, ts);
            ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
            ctx.lineWidth = 1;
            ctx.strokeRect(this.hoverPos.x * ts, this.hoverPos.y * ts, ts, ts);
        }

        const theme = this.currentArea.assetsTheme || 'meadow';
        for(let y=0; y<this.layout.height; y++) {
            for(let x=0; x<this.layout.width; x++) {
                const tile = this.layout.tiles[y][x];
                const config = this.ASSET_CONFIG[tile];
                if(config) {
                    if (config.name === 'wall') continue;
                    const imgName = `obs_${theme}_${config.name}`;
                    const img = imgManager.get(imgName);
                    const sizePx = config.size * ts;
                    if(img) {
                        const drawH = sizePx * 1.2; const yOffset = sizePx - drawH;
                        ctx.drawImage(img, x*ts, y*ts + yOffset, sizePx, drawH);
                    } else {
                        ctx.fillStyle = config.color; ctx.fillRect(x*ts, y*ts, sizePx, sizePx);
                    }
                }
                if(tile === 2) { 
                    const exitImg = imgManager.get('tile_exit');
                    if(exitImg) ctx.drawImage(exitImg, x*ts, y*ts, ts, ts);
                    else { ctx.fillStyle = '#3b82f6'; ctx.beginPath(); ctx.arc(x*ts+ts/2, y*ts+ts/2, ts/2, 0, Math.PI*2); ctx.fill(); }
                }
            }
        }
        
        this.layout.chests.forEach(c => {
            const cImg = imgManager.get(c.opened ? 'chest_open' : 'chest_closed');
            if(cImg) ctx.drawImage(cImg, c.x*ts, c.y*ts, ts, ts);
            else { ctx.fillStyle = c.opened ? '#9ca3af' : '#fbbf24'; ctx.fillRect(c.x*ts+4, c.y*ts+4, ts-8, ts-8); }
        });

        this.layout.npcs.forEach(n => {
            const nImg = imgManager.get(n.sprite);
            if(nImg) { ctx.drawImage(nImg, n.x*ts - ts*0.25, n.y*ts - ts*0.5, ts*1.5, ts*1.5); } 
            else { ctx.fillStyle = '#8b5cf6'; ctx.beginPath(); ctx.arc(n.x*ts+ts/2, n.y*ts+ts/2, ts/3, 0, Math.PI*2); ctx.fill(); }
            
            if(n.type==='quest') {
                if(!store.storyFlags[n.questId+'_done']) {
                    ctx.fillStyle='yellow'; ctx.font='bold 14px Arial'; ctx.fillText('!', n.x*ts+ts/2, n.y*ts - 10);
                } else {
                    ctx.fillStyle='#9ca3af'; ctx.font='bold 14px Arial'; ctx.fillText('?', n.x*ts+ts/2, n.y*ts - 10);
                }
            } else if(n.name==='村长' && !store.storyFlags['intro_chief_talked']) {
                ctx.fillStyle='yellow'; ctx.font='bold 14px Arial'; ctx.fillText('!', n.x*ts+ts/2, n.y*ts - 10);
            }
        });

        const pImg = imgManager.get('summoner');
        if(pImg) { ctx.drawImage(pImg, this.player.x*ts - ts*0.25, this.player.y*ts - ts*0.5, ts*1.5, ts*1.5); } 
        else { ctx.fillStyle = '#ef4444'; ctx.beginPath(); ctx.arc(this.player.x*ts+ts/2, this.player.y*ts+ts/2, ts/2.5, 0, Math.PI*2); ctx.fill(); }
    }
};

const battle = { 
    enemy: null, active: false, logHistory: [], mode: 'wild', // wild or arena
    
    async animate(elementId, animationClass) {
        const el = $(elementId); if (!el) return;
        el.classList.remove(animationClass);
        void el.offsetWidth; 
        el.classList.add(animationClass);
        await sleep(400); 
        el.classList.remove(animationClass);
    },
    
    calculateDamage(attacker, defender, skill) {
        const atkS = SPECIES[attacker.id];
        const defS = SPECIES[defender.id];
        
        let typeMult = 1.0;
        if (TYPE_MATRIX[skill.type] && TYPE_MATRIX[skill.type][defS.type]) {
            typeMult = TYPE_MATRIX[skill.type][defS.type];
        }

        let hitBonus = 0;
        if (typeMult > 1) hitBonus = 0.1;
        if (typeMult < 1) hitBonus = -0.1;
        
        let hitChance = skill.acc - (defS.evasion || 0) + hitBonus;
        if (attacker.status === 'burn') hitChance -= 0.1; 
        if (attacker.status === 'paralysis' && Math.random() < 0.25) return { dmg: 0, msg: '麻痹无法行动', isHit: false };
        if (attacker.status === 'sleep') return { dmg: 0, msg: '正在熟睡...', isHit: false };

        if (Math.random() > hitChance) return { dmg: 0, isHit: false, msg: '闪避' };
        
        let atkVal = attacker.atk;
        if (attacker.status === 'burn') atkVal = Math.floor(atkVal * 0.8); 
        
        const defVal = Math.floor(defender.atk * 0.4); 
        let rawDmg = Math.max(1, atkVal - defVal); 
        let dmg = Math.floor(rawDmg * (skill.pwr / 50));
        
        dmg = Math.floor(dmg * typeMult);
        
        const isCrit = Math.random() < ((atkS.crit_base || 0.05) + (skill.crit_mod || 0));
        if (isCrit) dmg = Math.floor(dmg * 1.5);
        
        dmg = Math.floor(dmg * (0.9 + Math.random() * 0.2)); 
        
        let addedStatus = null; 
        if (skill.status && !defender.status) { 
            if (Math.random() < skill.status_chance) { addedStatus = skill.status; } 
        }
        
        return { dmg: Math.max(1, dmg), isCrit, isHit: true, typeMult, addedStatus };
    },

    getCatchRate() {
        if (!this.enemy) return 0;
        if (this.mode === 'arena') return 0; // 竞技场无法直接捕捉
        const hpPercent = this.enemy.hp / this.enemy.max_hp;
        const speciesData = SPECIES[this.enemy.id];
        const baseRate = speciesData.catch_rate || 0.5;
        let statusBonus = this.enemy.status ? 0.2 : 0;
        
        const p = game.getPet();
        const typeMult = (TYPE_MATRIX[SPECIES[p.id].type] && TYPE_MATRIX[SPECIES[p.id].type][SPECIES[this.enemy.id].type]) || 1.0;
        let typeBonus = 0;
        if(typeMult > 1) typeBonus = 0.15;
        if(typeMult < 1) typeBonus = -0.1;

        let rate = (1 - hpPercent) * 0.5 + baseRate * 0.2 + statusBonus + typeBonus;
        return Math.floor(Math.max(0, Math.min(1, rate)) * 100);
    },

    getRunRate() {
        const p = game.getPet();
        if (!p || !this.enemy) return 0;
        if (this.mode === 'arena') return 50; // 竞技场逃跑率固定
        const typeMult = (TYPE_MATRIX[SPECIES[p.id].type] && TYPE_MATRIX[SPECIES[p.id].type][SPECIES[this.enemy.id].type]) || 1.0;
        let typeRunBonus = 0;
        if (typeMult > 1) typeRunBonus = 0.2;
        if (typeMult < 1) typeRunBonus = -0.2;
        
        const levelDiff = p.lvl - this.enemy.lvl;
        let rate = 0.5 + (levelDiff * 0.1) + typeRunBonus;
        return Math.floor(Math.max(0.1, Math.min(0.9, rate)) * 100);
    },

    init(area) { 
        this.mode = 'wild';
        if(!game.getPet()) { return toast("没有可用的宠物！"); }
        const p = game.getPet(); 
        if(p.hp<=0) { mapEngine.resume(); return toast('宠物需要治疗'); } 
        
        let enemies = area.enemies;
        const eId = enemies[rand(0, enemies.length-1)]; 
        const eBase = SPECIES[eId]; 
        
        let targetLvl = p.lvl + rand(-1, 2);
        if(targetLvl < 1) targetLvl = 1;

        this.enemy = { 
            ...eBase, id: eId, lvl: targetLvl, 
            max_hp: Math.floor(eBase.base.hp + eBase.growth.hp * targetLvl),
            hp: 0, 
            atk: Math.floor(eBase.base.atk + eBase.growth.atk * targetLvl),
            status: null 
        };
        this.enemy.hp = this.enemy.max_hp;
        
        this.active = true; 
        router.go('battle'); 
        this.logHistory = []; $('bat-log').innerHTML = ''; 
        
        this.log(`遭遇了野生 ${this.enemy.name} (Lv.${this.enemy.lvl})! [${TYPE_NAMES[this.enemy.type]}系]`); 
        
        this.updateView(); 
        this.unlockMenu(); 
        this.mainMenu(); 
    }, 
    
    // 专门为竞技场初始化的战斗
    initArena(petId) {
        this.mode = 'arena';
        if(!game.getPet()) { return toast("没有可用的宠物！"); }
        const p = game.getPet(); 
        if(p.hp<=0) { return toast('宠物需要治疗'); } 

        const eBase = SPECIES[petId];
        // 竞技场等级设置：比玩家高一点或者固定
        let targetLvl = Math.max(1, p.lvl + rand(0, 3)); 
        if (eBase.stage === 4) targetLvl = Math.max(50, p.lvl + 5); // 究极体更强

        this.enemy = {
            ...eBase, id: petId, lvl: targetLvl,
            max_hp: Math.floor(eBase.base.hp + eBase.growth.hp * targetLvl),
            hp: 0,
            atk: Math.floor(eBase.base.atk + eBase.growth.atk * targetLvl),
            status: null
        };
        this.enemy.hp = this.enemy.max_hp;
        
        this.active = true; 
        router.go('battle'); 
        this.logHistory = []; $('bat-log').innerHTML = ''; 
        $('arena-preview-modal').classList.add('hidden'); // 关闭预览窗口
        
        this.log(`挑战开始！对手是 ${this.enemy.name} (Lv.${this.enemy.lvl})！`); 
        this.updateView(); 
        this.unlockMenu(); 
        this.mainMenu(); 
    },
    
    updateView() { 
        const p = game.getPet(); const e = this.enemy; 
        if(!p || !e) return;

        setTxt('bat-p-name', SPECIES[p.id].name);
        const pHpPct = Math.max(0, (p.hp / p.max_hp) * 100);
        setWidth('bat-p-hp', pHpPct);
        setTxt('bat-p-hp-text', `${Math.ceil(Math.max(0, p.hp))}/${p.max_hp}`);
        
        setTxt('bat-e-name', e.name);
        const eHpPct = Math.max(0, (e.hp / e.max_hp) * 100);
        setWidth('bat-e-hp', eHpPct);
        setTxt('bat-e-hp-text', `${Math.ceil(Math.max(0, e.hp))}/${e.max_hp}`);
        setTxt('bat-e-lvl', e.lvl);
        
        setTxt('bat-e-type', TYPES[e.type].name);
        setClass('bat-e-type', `type-badge ${TYPES[e.type].color}`);
        
        // 竞技场模式下显示特殊的文本
        if (this.mode === 'arena') {
            setTxt('bat-catch-rate', '(不可捕捉)');
            setTxt('bat-run-rate', '(投降)');
        } else {
            setTxt('bat-catch-rate', `(${this.getCatchRate()}%)`);
            setTxt('bat-run-rate', `(${this.getRunRate()}%)`);
        }

        const pImgContainer = $('bat-p-sprite');
        if(pImgContainer && pImgContainer.getAttribute('data-id') !== p.id) {
             pImgContainer.innerHTML = getPetImage(p.id); 
             pImgContainer.setAttribute('data-id', p.id);
        }
        const eImgContainer = $('bat-e-sprite');
        if(eImgContainer && eImgContainer.getAttribute('data-id') !== e.id) {
             eImgContainer.innerHTML = getPetImage(e.id);
             eImgContainer.setAttribute('data-id', e.id);
        }

        setTxt('bat-pot-count', store.inventory.potion || 0);
        setTxt('bat-ball-count', store.inventory.ball || 0);
        
        this.renderStatusIcon('p', p.status); 
        this.renderStatusIcon('e', e.status);
    }, 
    
    forceUpdateUI() { setTimeout(() => this.updateView(), 0); },

    renderStatusIcon(target, status) {
        const el = $(`bat-${target}-status`); if (!el) return;
        if (status && STATUS_EFFECTS[status]) { 
            el.innerText = STATUS_EFFECTS[status].icon; 
            el.className = `status-icon animate-bounce ${STATUS_EFFECTS[status].color} ml-2`; 
            el.classList.remove('hidden'); 
        } else { el.classList.add('hidden'); }
    },
    
    lockMenu() {
        const menu = $('bat-menu-container');
        if(menu) menu.classList.add('opacity-50', 'pointer-events-none');
    },
    unlockMenu() {
        const menu = $('bat-menu-container');
        if(menu) menu.classList.remove('opacity-50', 'pointer-events-none');
    },

    mainMenu() { 
        const mMain = $('bat-menu-main'); if(mMain) mMain.classList.remove('hidden'); 
        const mSkills = $('bat-menu-skills'); if(mSkills) mSkills.classList.add('hidden'); 
        const mSwitch = $('bat-menu-switch'); if(mSwitch) mSwitch.classList.add('hidden'); 
    }, 
    
    showSkills() { 
        $('bat-menu-main').classList.add('hidden'); 
        const div = $('bat-menu-skills'); 
        div.classList.remove('hidden');
        div.innerHTML=''; 
        
        SPECIES[game.getPet().id].skills.forEach(k => { 
            const sk = SKILLS[k]; 
            const btn = document.createElement('button'); 
            btn.className = 'btn-game bg-gray-700 text-white rounded-lg p-2 text-xs font-bold hover:bg-indigo-600 flex flex-col items-center justify-center'; 
            btn.innerHTML = `<span class="text-sm">${sk.name}</span><div class="flex gap-2 mt-1"><span class="text-[9px] opacity-70 text-${TYPES[sk.type].text.split('-')[1]}-400">${TYPES[sk.type].name}</span><span class="text-[9px] text-yellow-500">PWR ${sk.pwr}</span></div>`; 
            btn.onclick = () => this.turn(sk); 
            div.appendChild(btn); 
        }); 
        
        const back = document.createElement('button'); 
        back.className = 'btn-game text-gray-400 text-xs hover:text-white'; 
        back.innerText = '返回'; 
        back.onclick = () => this.mainMenu(); 
        div.appendChild(back); 
    }, 
    
    log(msg) { 
        this.logHistory.push(msg); 
        if (this.logHistory.length > 6) this.logHistory.shift(); 
        const el = $('bat-log'); 
        if(el) {
            el.innerHTML = this.logHistory.map(m => `<div>${m}</div>`).join(''); 
            el.scrollTop = el.scrollHeight; 
        }
    },
    
    async turn(sk) { 
        if(!this.active) return; 
        this.lockMenu(); 
        this.mainMenu(); 
        
        const p = game.getPet(); 
        const e = this.enemy; 

        const canMove = !(p.status === 'sleep' || (p.status === 'paralysis' && Math.random() < 0.25));
        
        if (canMove) {
            await this.animate('bat-p-sprite', 'action-attack-p'); 
            const res = this.calculateDamage(p, e, sk);
            
            if(res.msg && !res.isHit && res.msg !== '闪避') {
                this.log(res.msg); 
            } else if (res.isHit === false) { 
                this.log(`你的攻击被闪避了！`);
                this.showFloatingText('bat-e-sprite', 'MISS', 'gray');
            } else { 
                e.hp -= res.dmg; 
                this.forceUpdateUI(); 
                await this.animate('bat-e-sprite', 'action-hit'); 
                
                this.showFloatingText('bat-e-sprite', `-${res.dmg}`, res.isCrit ? 'yellow' : 'white');
                
                let extra = '';
                if(res.typeMult > 1) extra = ' 效果拔群!';
                if(res.typeMult < 1) extra = ' 收效甚微...';
                if(res.isCrit) extra += ' 会心一击!';
                this.log(`造成 ${res.dmg} 伤害!${extra}`);
                
                if(res.addedStatus) {
                    e.status = res.addedStatus;
                    this.log(`${e.name} ${STATUS_EFFECTS[e.status].name}了!`);
                }
            }
            if (e.status === 'sleep' && res.isHit) {
                if(Math.random() < 0.3) { e.status = null; this.log(`${e.name} 被打醒了！`); }
            }
        } else {
            this.log('你无法行动！');
            await sleep(500);
        }

        if(e.hp <= 0) { 
            e.hp = 0; this.forceUpdateUI(); 
            await sleep(500); 
            this.win(); return; 
        }

        await sleep(800);
        await this.enemyTurn();
    }, 
    
    async enemyTurn() {
        if(!this.active) return;
        const p = game.getPet(); const e = this.enemy;
        
        const canMove = !(e.status === 'sleep' || (e.status === 'paralysis' && Math.random() < 0.25));
        
        if(canMove) {
            await this.animate('bat-e-sprite', 'action-attack-e'); 
            const eSkId = SPECIES[e.id].skills[rand(0, SPECIES[e.id].skills.length-1)];
            const eSk = SKILLS[eSkId];
            
            const res = this.calculateDamage(e, p, eSk);
            
            if(res.msg && !res.isHit && res.msg !== '闪避') {
                this.log(`${e.name} ${res.msg}`);
            } else if(res.isHit === false) {
                this.log(`你躲开了敌人的攻击！`);
                this.showFloatingText('bat-p-sprite', 'MISS', 'gray');
            } else {
                p.hp -= res.dmg;
                this.forceUpdateUI();
                await this.animate('bat-p-sprite', 'action-hit');
                
                this.showFloatingText('bat-p-sprite', `-${res.dmg}`, 'red');
                this.log(`受到 ${res.dmg} 点伤害！`);
                
                if(res.addedStatus) {
                    p.status = res.addedStatus;
                    this.log(`你${STATUS_EFFECTS[p.status].name}了！`);
                }
            }
            if (p.status === 'sleep' && res.isHit) {
                if(Math.random() < 0.3) { p.status = null; this.log(`你被打醒了！`); }
            }
        } else {
            this.log(`${e.name} 无法行动。`);
            await sleep(500);
        }

        const applyStatus = (target, name, elemId) => {
            if(target.status === 'burn' || target.status === 'poison') {
                const dmg = Math.floor(target.max_hp / 8);
                target.hp -= dmg;
                this.showFloatingText(elemId, `-${dmg}`, 'purple');
                this.log(`${name} 受到异常状态伤害`);
            }
        };
        applyStatus(p, '你', 'bat-p-sprite');
        applyStatus(e, e.name, 'bat-e-sprite');
        
        this.forceUpdateUI();
        
        if(p.hp <= 0) {
            p.hp = 0; this.forceUpdateUI();
            await sleep(1000);
            this.playerFaint();
        } else if (e.hp <= 0) {
            e.hp = 0; this.forceUpdateUI();
            await sleep(500); 
            this.win();
        } else {
            this.mainMenu(); 
            this.unlockMenu(); 
        }
    },
    
    playerFaint() { 
        this.active=false; 
        toast('战斗失败...'); 
        game.save(); 
        setTimeout(() => {
            if(this.mode === 'arena') router.go('arena');
            else mapEngine.resume();
        }, 1500); 
    },
    
    async tryCatch() { 
        if (this.mode === 'arena') return toast('竞技场中禁止捕捉！');
        if(store.inventory.ball<=0) return toast('没有捕网'); 
        store.inventory.ball--; 
        this.forceUpdateUI();
        this.lockMenu();
        
        const hpPercent = this.enemy.hp / this.enemy.max_hp; 
        const speciesData = SPECIES[this.enemy.id]; 
        const baseRate = speciesData.catch_rate || 0.5; 
        let statusBonus = this.enemy.status ? 0.2 : 0; 
        
        const p = game.getPet();
        const typeMult = (TYPE_MATRIX[SPECIES[p.id].type] && TYPE_MATRIX[SPECIES[p.id].type][SPECIES[this.enemy.id].type]) || 1.0;
        let typeBonus = 0;
        if(typeMult > 1) typeBonus = 0.15; 
        if(typeMult < 1) typeBonus = -0.1; 

        const rate = (1 - hpPercent) * 0.5 + baseRate * 0.2 + statusBonus + typeBonus; 
        
        this.log(`扔出了捕兽网... (概率:${Math.floor(Math.max(0,Math.min(1,rate))*100)}%)`); 
        await sleep(1000); 
        
        if(Math.random() < rate) { 
            this.log(`成功捕捉 ${this.enemy.name}！`);
            game.addPet(this.enemy.id, this.enemy.lvl); 
            game.save(); 
            this.active=false; 
            await sleep(1500); 
            mapEngine.resume(); 
        } else { 
            this.log(`捕捉失败！`); 
            await sleep(500);
            await this.enemyTurn(); 
        } 
    }, 
    
    async run() { 
        this.lockMenu();
        if (this.mode === 'arena') {
            this.log('弃权投降...');
            await sleep(800);
            this.active = false;
            toast('已退出竞技场');
            router.go('arena');
            return;
        }

        const p = game.getPet(); 
        const typeMult = (TYPE_MATRIX[SPECIES[p.id].type] && TYPE_MATRIX[SPECIES[p.id].type][SPECIES[this.enemy.id].type]) || 1.0;
        let typeRunBonus = 0;
        if (typeMult > 1) typeRunBonus = 0.2; 
        if (typeMult < 1) typeRunBonus = -0.2; 
        
        const levelDiff = p.lvl - this.enemy.lvl; 
        let rate = 0.5 + (levelDiff * 0.1) + typeRunBonus; 
        rate = Math.max(0.1, Math.min(0.9, rate));

        this.log(`正在尝试逃跑... (概率:${Math.floor(rate*100)}%)`); 
        await sleep(800); 
        
        if (Math.random() < rate) { 
            this.active=false; 
            toast('成功逃跑');
            mapEngine.resume(); 
        } else { 
            this.log('逃跑失败！'); 
            await sleep(500);
            await this.enemyTurn(); 
        } 
    }, 
    
    usePotion() { 
        if(store.inventory.potion>0) { 
            store.inventory.potion--; 
            const p=game.getPet(); 
            p.hp = Math.min(p.max_hp, p.hp+50); 
            p.status = null; 
            this.forceUpdateUI();
            this.log('使用了伤药，恢复50HP并解除异常。'); 
            this.lockMenu();
            setTimeout(() => this.enemyTurn(), 800); 
        } else { 
            toast('没有伤药'); 
        } 
    }, 
    
    win() { 
        this.active=false; 
        const gold = rand(30, 60) * (this.mode === 'arena' ? 2 : 1); 
        const xpGain = Math.floor((30 + this.enemy.lvl * 15) * 1.5 * (this.mode === 'arena' ? 1.5 : 1)); 
        store.gold += gold; 
        game.gainXp(xpGain); 
        
        const drops = [];

        // 竞技场特殊掉落逻辑
        if (this.mode === 'arena') {
            // 记录冷却时间 (5分钟)
            store.arenaCooldowns[this.enemy.id] = Date.now() + 5 * 60 * 1000;
            
            // 掉落道具概率
            if (Math.random() < 0.3) {
                store.inventory.xp_potion++;
                drops.push({ type: 'item', id: 'xp_potion', name: '经验药水', icon: '🧪' });
            }
            
            // 掉落宠物概率 (Boss 10%, 普通 20%)
            const dropChance = this.enemy.stage === 4 ? 0.1 : 0.2;
            if (Math.random() < dropChance) {
                game.addPet(this.enemy.id, 1); // 获得1级幼崽
                drops.push({ type: 'pet', id: this.enemy.id, name: this.enemy.name, icon: '🐾' });
            }
        }

        game.save(); 
        
        // 调用战斗结算弹窗
        game.showBattleResult(gold, xpGain, drops, () => {
            if (this.mode === 'arena') router.go('arena');
            else mapEngine.resume();
        });
    },
    
    switchPetMenu() {
        $('bat-menu-main').classList.add('hidden');
        $('bat-menu-switch').classList.remove('hidden');
        const container = $('bat-switch-list');
        container.innerHTML = '';
        store.team.forEach(uid => {
            const pet = store.pets.find(p => String(p.uid) === uid);
            if (!pet) return;
            const s = SPECIES[pet.id];
            const isCurrent = String(pet.uid) === String(game.getPet().uid);
            const btn = document.createElement('button');
            btn.className = `w-full p-2 rounded flex items-center justify-between border ${isCurrent ? 'bg-indigo-900/50 border-indigo-500 cursor-default opacity-60' : 'bg-gray-700 hover:bg-gray-600 border-gray-600 cursor-pointer'}`;
            if (isCurrent) btn.disabled = true;
            btn.innerHTML = `<div class="flex items-center gap-2"><div class="w-8 h-8 bg-black/30 rounded flex items-center justify-center overflow-hidden"><img src="./images/${pet.id}.png" class="w-full h-full object-contain"></div><div class="text-left"><div class="font-bold text-xs text-white">${s.name}</div><div class="text-[9px] text-gray-400">Lv.${pet.lvl}</div></div></div><div class="font-mono text-xs ${pet.hp > 0 ? 'text-green-400' : 'text-red-400'}">${Math.ceil(pet.hp)}/${pet.max_hp}</div>`;
            if (!isCurrent && pet.hp > 0) { btn.onclick = () => this.executeSwitch(uid); }
            container.appendChild(btn);
        });
        const backBtn = document.createElement('button'); backBtn.className = "w-full mt-2 py-1 text-xs text-gray-400 hover:text-white"; backBtn.innerText = "返回"; backBtn.onclick = () => this.mainMenu(); container.appendChild(backBtn);
    },
    executeSwitch(uid) {
        const idx = store.pets.findIndex(p => String(p.uid) === uid);
        if (idx === -1) return;
        store.activeIdx = idx;
        const newPet = game.getPet();
        this.log(`去吧！${SPECIES[newPet.id].name}！`);
        this.updateView(); 
        $('bat-menu-switch').classList.add('hidden'); 
        this.lockMenu();
        setTimeout(() => this.enemyTurn(), 800); 
    },

    showFloatingText(targetId, text, colorClass) { 
        const target = $(targetId); if(!target) return; 
        const rect = target.getBoundingClientRect(); 
        const el = document.createElement('div'); 
        el.className = `floating-text ${colorClass === 'red' ? 'text-red-500' : colorClass === 'green' ? 'text-green-500' : colorClass==='yellow'?'text-yellow-400': colorClass==='purple'?'text-purple-400':'text-white'} font-black text-2xl absolute z-[100] pointer-events-none drop-shadow-[0_2px_2px_rgba(0,0,0,0.8)]`; 
        el.innerText = text; 
        el.style.left = (rect.left + rect.width / 2) + 'px'; 
        el.style.top = (rect.top + 20) + 'px'; 
        document.body.appendChild(el); 
        setTimeout(() => el.remove(), 1000); 
    }
};

const game = {
    dexMode: 'pet', // 新增：控制背包显示模式
    arenaStage: 1, // 新增：竞技场当前页签

    init() {
        if (typeof renderStartIcons === 'function') renderStartIcons();
        if (localStorage.getItem('pk_evo_save')) $('load-btn').classList.remove('hidden');
        
        const isGod = localStorage.getItem('pk_god_mode') === 'true';
        if (isGod) { 
            const t = $('start-title'); if(t) { t.innerText = "欢迎创世者来到宠物王国"; t.classList.add('text-yellow-400'); }
            const s = $('starter-selection'); if(s) s.classList.add('hidden'); 
            const g = $('god-enter-btn'); if(g) g.classList.remove('hidden'); 
        }

        let progress = 0;
        imgManager.preloadAll((percent) => {
            progress = percent;
            setWidth('loading-bar', progress);
            setTxt('loading-percent', `${progress}%`);
            if (progress >= 100) { 
                setTimeout(() => { 
                    const s = $('loading-screen'); 
                    if(s) { s.style.opacity = '0'; setTimeout(() => s.classList.add('hidden'), 500); }
                }, 500); 
            }
        });
        
        mapEngine.init();
    },
    
    startGame(type) {
        store.pets = []; store.gold = 100; store.inventory = { potion: 3, ball: 3, guide_book: 0, xp_potion: 1 }; // 初始送1瓶经验水
        store.unlockedAreas = ['meadow']; store.storyFlags = {}; store.unlockedRings = ['ring_silver']; store.team = [];
        this.addPet(type + '_1', 5);
        this.save(); story.start('intro'); router.go('home');
    },

    enterAsGod() {
        const saved = localStorage.getItem('pk_evo_save');
        if (!saved) {
            store.gold = 999999; store.pets = []; store.inventory = { potion: 999, ball: 999, guide_book: 1, xp_potion: 999 };
            store.unlockedAreas = ['meadow', 'volcano', 'beach', 'sky', 'graveyard', 'arena']; store.unlockedRings = ['ring_silver', 'ring_gold', 'ring_overlord']; store.storyFlags = {};
            store.arenaCooldowns = {};
            this.addPet('wood_4', 100); this.save();
        } else { this.loadGame(); return; }
        router.go('home'); toast('创世者降临！');
    },
    
    loadGame() {
        const saved = localStorage.getItem('pk_evo_save');
        if (saved) {
            const data = JSON.parse(saved);
            store.gold = data.gold; store.pets = data.pets; store.activeIdx = data.activeIdx;
            store.inventory = data.inventory; 
            if(!store.inventory.xp_potion) store.inventory.xp_potion = 0;
            store.unlockedAreas = data.unlockedAreas || ['meadow']; store.pokedex = data.pokedex || []; store.storyFlags = data.storyFlags || {}; store.unlockedRings = data.unlockedRings || ['ring_silver']; store.team = data.team || (store.pets.length > 0 ? [String(store.pets[0].uid)] : []);
            store.arenaCooldowns = data.arenaCooldowns || {};
            router.go('home'); toast('存档读取成功');
        }
    },
    
    save() { localStorage.setItem('pk_evo_save', JSON.stringify(store)); },
    getPet() { if(!store.pets || store.pets.length === 0) return null; return store.pets[store.activeIdx]; },
    
    addPet(id, lvl) {
        const uid = Date.now() + Math.random().toString(36).substr(2, 5);
        const species = SPECIES[id]; const base = species.base; const growth = species.growth;
        const maxHp = Math.floor(base.hp + growth.hp * lvl); const atk = Math.floor(base.atk + growth.atk * lvl);
        const newPet = { uid: uid, id: id, lvl: lvl, xp: 0, max_xp: lvl * 100, hp: maxHp, max_hp: maxHp, atk: atk, bond: 0, status: null };
        store.pets.push(newPet);
        if (!store.pokedex.includes(id)) store.pokedex.push(id);
        const ringKey = store.unlockedRings[store.unlockedRings.length - 1] || 'ring_silver'; const maxSlots = RINGS[ringKey] ? RINGS[ringKey].slots : 4;
        if (store.team.length < maxSlots) { store.team.push(String(uid)); }
        this.updateHud();
    },
    
    // --- 经验获取与升级核心 ---
    gainXp(amount) {
        const p = this.getPet(); 
        p.xp += amount;
        
        let leveledUp = false;
        while(p.xp >= p.max_xp) {
            p.xp -= p.max_xp; 
            p.lvl++; 
            p.max_xp = p.lvl * 100;
            
            const species = SPECIES[p.id];
            p.max_hp += species.growth.hp; 
            p.hp = p.max_hp; 
            p.atk += species.growth.atk;
            leveledUp = true;
            
            if (species.evo && p.lvl >= species.evo) {
                const nextId = species.next;
                if (nextId && SPECIES[nextId]) {
                    setTimeout(() => {
                        this.showConfirm(`你的 ${species.name} 想要进化！允许吗？`, () => {
                            p.id = nextId; const newS = SPECIES[nextId];
                            p.max_hp = Math.floor(newS.base.hp + newS.growth.hp * p.lvl); 
                            p.hp = p.max_hp; 
                            p.atk = Math.floor(newS.base.atk + newS.growth.atk * p.lvl);
                            if (!store.pokedex.includes(nextId)) store.pokedex.push(nextId);
                            this.renderHome(); 
                            toast(`进化成功！变为了 ${newS.name}`); 
                            story.start('evolution'); 
                            this.save();
                        });
                    }, 1000);
                    break;
                }
            }
        }
        
        if(leveledUp) toast(`升级了! Lv.${p.lvl}`);
        this.renderHome();
    },
    
    updateHud() {
        setTxt('hud-gold', store.gold);
        setTxt('hud-potions', store.inventory.potion);
        setTxt('hud-balls', store.inventory.ball);
        const ringKey = store.unlockedRings[store.unlockedRings.length - 1] || 'ring_silver'; 
        const maxSlots = RINGS[ringKey] ? RINGS[ringKey].slots : 4;
        setTxt('hud-team-size', `${store.team.length}/${maxSlots}`);
    },
    
    renderHome() {
        const p = this.getPet(); if (!p) return; const s = SPECIES[p.id];
        
        const spr = $('home-sprite'); if(spr) spr.innerHTML = getPetImage(p.id);
        setTxt('home-name', s.name);
        setTxt('home-type', TYPES[s.type].name);
        setClass('home-type', `type-badge ${TYPES[s.type].color}`);
        setTxt('home-lvl', p.lvl);
        // 修复了这里的语法错误，加上了闭合括号
        setTxt('home-stage-name', s.stage === 4 ? 'ULTIMATE' : `STAGE ${s.stage}`);
        
        setTxt('home-hp-text', `${Math.ceil(p.hp)}/${p.max_hp}`);
        setWidth('home-hp-bar', (p.hp / p.max_hp) * 100);
        
        setTxt('home-xp-text', `${Math.floor(p.xp)}/${p.max_xp}`);
        setWidth('home-xp-bar', Math.min(100, (p.xp / p.max_xp) * 100));
        
        setTxt('home-bond-text', `${p.bond}%`);
        setWidth('home-bond-bar', Math.min(100, p.bond));
        
        setTxt('home-idx-display', `${store.activeIdx + 1}/${store.pets.length}`);
        const evoText = s.evo ? `距离进化还需 ${Math.max(0, s.evo - p.lvl)} 级` : '已达到最终形态'; 
        setTxt('home-evo-text', evoText);
        
        setTxt('train-current-lv', p.lvl);
        setTxt('train-potion-own', store.inventory.xp_potion || 0);
        
        const inTeamBadge = $('home-in-team');
        if (inTeamBadge) {
            if (store.team.includes(String(p.uid))) { inTeamBadge.classList.remove('hidden'); } else { inTeamBadge.classList.add('hidden'); }
        }
        this.updateHud();
    },
    
    switchPet(dir) { const len = store.pets.length; if (len <= 1) return; store.activeIdx = (store.activeIdx + dir + len) % len; this.renderHome(); this.save(); },
    rest() { const p = this.getPet(); if(!p) return; p.hp = p.max_hp; p.status = null; toast('体力已恢复！'); this.renderHome(); this.save(); },
    feed() { if (store.gold >= 10) { store.gold -= 10; const p = this.getPet(); p.bond = Math.min(100, p.bond + 5); toast('美味！羁绊+5'); this.save(); } else { toast('金币不足！'); } },
    interact() { const p = this.getPet(); const bubble = $('interact-bubble'); if(bubble) { bubble.style.opacity = '1'; bubble.style.transform = 'translateY(0)'; } p.bond = Math.min(100, p.bond + 1); this.renderHome(); setTimeout(() => { if(bubble) { bubble.style.opacity = '0'; bubble.style.transform = 'translateY(-16px)'; } }, 1500); },
    
    useXpPotion() {
        if(store.inventory.xp_potion > 0) {
            store.inventory.xp_potion--;
            this.gainXp(500); 
            toast('使用了经验药水！经验 +500');
            this.save();
        } else {
            toast('经验药水不足！请去商店购买。');
        }
    },
    
    renderMap() {
        const container = $('area-list'); if(!container) return; container.innerHTML = '';
        AREAS.forEach(area => {
            const unlocked = store.unlockedAreas.includes(area.id);
            const div = document.createElement('div');
            div.className = `group relative overflow-hidden rounded-3xl h-64 border transition-all duration-300 ${unlocked ? 'border-gray-600 hover:border-indigo-400 cursor-pointer hover:shadow-2xl hover:-translate-y-2' : 'border-gray-800 opacity-50 grayscale'}`;
            div.innerHTML = `<div class="absolute inset-0 bg-gradient-to-br ${area.bg} opacity-80 group-hover:opacity-100 transition-opacity"></div><div class="absolute inset-0 p-6 flex flex-col justify-between z-10"><div><h3 class="text-3xl font-black text-white mb-2 drop-shadow-md tracking-wider">${area.name}</h3><div class="text-xs font-bold bg-black/30 text-white inline-block px-3 py-1 rounded backdrop-blur-sm">Lv.${area.lvl}</div></div><div class="space-y-2"><p class="text-xs text-gray-200 line-clamp-2 font-medium leading-relaxed">${area.desc}</p><div class="flex items-center gap-2 pt-2 border-t border-white/20"><div class="text-[10px] uppercase font-bold text-white/60 tracking-widest">敌   人</div><div class="flex -space-x-2">${area.enemies.slice(0,3).map(e => `<div class="w-6 h-6 rounded-full bg-black/50 border border-white/30 flex items-center justify-center text-[10px] overflow-hidden"><img src="./images/${e}.png" class="w-full h-full object-cover"></div>`).join('')}</div></div></div>${!unlocked ? `<div class="absolute inset-0 bg-black/60 flex items-center justify-center flex-col gap-2 backdrop-blur-sm"><span class="text-3xl">🔒</span><span class="text-xs font-bold text-gray-400 uppercase tracking-widest">LOCKED</span></div>` : ''}</div>`;
            if (unlocked) { div.onclick = () => mapEngine.start(area); }
            container.appendChild(div);
        });
    },
    
    // --- 竞技场模块 ---
    renderArena() {
        this.renderArenaList(this.arenaStage);
    },

    switchArenaTab(stage) {
        this.arenaStage = stage;
        document.querySelectorAll('.arena-tab-btn').forEach(b => b.classList.remove('active', 'bg-indigo-600', 'text-white'));
        const activeBtn = $(`arena-tab-${stage}`);
        if(activeBtn) activeBtn.classList.add('active', 'bg-indigo-600', 'text-white');
        this.renderArenaList(stage);
    },

    renderArenaList(stage) {
        const container = $('arena-grid');
        if (!container) return;
        container.innerHTML = '';
        
        // 筛选对应形态的宠物
        const pets = Object.keys(SPECIES).filter(key => SPECIES[key].stage === stage);
        
        pets.forEach(petId => {
            const s = SPECIES[petId];
            const cooldownEnd = store.arenaCooldowns[petId] || 0;
            const isCooling = Date.now() < cooldownEnd;
            
            const card = document.createElement('div');
            card.className = `glass-panel-light p-4 relative group hover:bg-white/5 transition-all cursor-pointer border ${isCooling ? 'border-red-900/50 opacity-60' : 'border-gray-700 hover:border-indigo-400'}`;
            
            // 冷却遮罩
            const cooldownOverlay = isCooling ? `
                <div class="absolute inset-0 bg-black/80 rounded-xl z-20 flex flex-col items-center justify-center">
                    <span class="text-2xl mb-2">⏳</span>
                    <span class="text-xs font-bold text-red-400">休息中</span>
                    <span class="text-[10px] text-gray-500 font-mono mt-1">${Math.ceil((cooldownEnd - Date.now())/1000/60)}m</span>
                </div>
            ` : '';

            card.innerHTML = `
                ${cooldownOverlay}
                <div class="aspect-square mb-3 relative bg-black/20 rounded-lg p-2">
                    ${getPetImage(petId)}
                    <div class="absolute top-0 left-0 bg-black/60 text-white text-[10px] px-2 py-0.5 rounded-br font-bold border-b border-r border-white/10">Lv.${stage === 4 ? 'BOSS' : '??'}</div>
                </div>
                <div class="text-center">
                    <div class="font-bold text-white text-sm truncate">${s.name}</div>
                    <div class="flex items-center justify-center gap-2 mt-1">
                        <span class="type-badge ${TYPES[s.type].color} text-[9px] px-1.5 py-0.5">${TYPES[s.type].name}</span>
                        <span class="text-[10px] text-gray-400">战力: ${s.base.atk * 10}</span>
                    </div>
                </div>
            `;
            
            if (!isCooling) {
                card.onclick = () => this.showArenaPreview(petId);
            } else {
                card.onclick = () => toast('该宠物正在休息，请稍后再来挑战！');
            }
            
            container.appendChild(card);
        });
    },

    showArenaPreview(petId) {
        const s = SPECIES[petId];
        const modal = $('arena-preview-modal');
        if (modal) {
            $('arena-preview-img').innerHTML = getPetImage(petId);
            setTxt('arena-preview-name', s.name);
            setTxt('arena-preview-desc', s.desc);
            setTxt('arena-preview-type', TYPES[s.type].name);
            setClass('arena-preview-type', `type-badge ${TYPES[s.type].color}`);
            
            // 模拟掉落预览
            const drops = [
                {icon: '💰', name: '大量金币'},
                {icon: '✨', name: '海量经验'},
                {icon: '🧪', name: '经验药水(30%)'},
                {icon: '🎁', name: '宠物本体(20%)'}
            ];
            
            const dropContainer = $('arena-preview-drops');
            dropContainer.innerHTML = drops.map(d => `
                <div class="flex flex-col items-center gap-1 bg-black/30 p-2 rounded-lg">
                    <span class="text-xl">${d.icon}</span>
                    <span class="text-[9px] text-gray-400">${d.name}</span>
                </div>
            `).join('');
            
            // 绑定开始按钮
            const startBtn = $('arena-start-btn');
            startBtn.onclick = () => this.startArenaBattle(petId);
            
            modal.classList.remove('hidden');
        }
    },

    startArenaBattle(petId) {
        battle.initArena(petId);
    },
    
    renderShop() {
        const basicContainer = $('shop-basic-items'); if(!basicContainer) return; basicContainer.innerHTML = '';
        const basicItems = [
            { id: 'potion', name: '回复药水', price: 50, icon: '💊', desc: '恢复 50 点生命值' },
            { id: 'ball', name: '捕兽网', price: 100, icon: '🕸️', desc: '用于捕捉野生精灵' },
            { id: 'xp_potion', name: '经验药水', price: 200, icon: '🧪', desc: '神奇药水，提供500点经验' } 
        ];
        
        basicItems.forEach(item => {
            const el = document.createElement('div');
            el.className = 'flex items-center justify-between bg-gray-800/50 p-4 rounded-xl border border-gray-700 hover:bg-gray-700/50 transition-colors group';
            el.innerHTML = `<div class="flex items-center gap-4"><div class="text-2xl bg-gray-900 w-12 h-12 rounded-lg flex items-center justify-center shadow-inner">${item.icon}</div><div><div class="font-bold text-white group-hover:text-indigo-300 transition-colors">${item.name}</div><div class="text-xs text-gray-500">${item.desc}</div></div></div><button onclick="game.buyItem('${item.id}', ${item.price})" class="px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-white rounded-lg font-bold text-sm shadow-lg flex items-center gap-1 active:scale-95 transition-all"><span>$${item.price}</span></button>`;
            basicContainer.appendChild(el);
        });

        const specialContainer = $('shop-special-items'); if(!specialContainer) return; specialContainer.innerHTML = '';
        Object.entries(RINGS).forEach(([key, ring]) => {
            if (key === 'ring_silver') return; 
            const owned = store.unlockedRings.includes(key);
            const el = document.createElement('div');
            el.className = `flex items-center justify-between p-4 rounded-xl border transition-colors group ${owned ? 'bg-green-900/20 border-green-800/50' : 'bg-gray-800/30 border-yellow-500/20 hover:border-yellow-500/50'}`;
            el.innerHTML = `<div class="flex items-center gap-4"><div class="text-2xl w-12 h-12 rounded-lg flex items-center justify-center shadow-inner bg-black/30 ${ring.color}">${ring.icon}</div><div><div class="font-bold text-white ${owned ? 'text-green-400' : 'group-hover:text-yellow-300'} transition-colors">${ring.name}</div><div class="text-xs text-gray-500">${ring.desc}</div></div></div>${owned ? `<span class="px-4 py-2 text-green-500 font-bold text-sm bg-green-900/30 rounded-lg border border-green-800/50">已拥有</span>` : `<button onclick="game.buyRing('${key}', ${ring.price})" ${ring.locked ? 'disabled' : ''} class="px-4 py-2 ${ring.locked ? 'bg-gray-700 text-gray-500 cursor-not-allowed' : 'bg-yellow-600 hover:bg-yellow-500 text-white shadow-lg shadow-yellow-600/20'} rounded-lg font-bold text-sm flex items-center gap-1 active:scale-95 transition-all">${ring.locked ? '未解锁' : `<span>$${ring.price}</span>`}</button>`}`;
            specialContainer.appendChild(el);
        });
    },

    buyItem(id, price) {
        if (store.gold >= price) { store.gold -= price; store.inventory[id]++; toast(`购买成功！`); this.updateHud(); this.save(); } else { toast('金币不足！'); }
    },

    buyRing(key, price) {
        if (store.gold >= price) { store.gold -= price; store.unlockedRings.push(key); toast(`成功升级空间戒！容量增加！`); this.renderShop(); this.updateHud(); this.save(); } else { toast('金币不足！'); }
    },
    
    setDexMode(mode) {
        this.dexMode = mode;
        this.renderDex();
    },

    renderDex() {
        const container = $('dex-grid'); 
        if(!container) return;
        container.innerHTML = '';
        
        const tabContainer = document.createElement('div');
        tabContainer.className = 'col-span-full flex gap-4 mb-4 border-b border-gray-700 pb-4';
        tabContainer.innerHTML = `
            <button onclick="game.setDexMode('pet')" class="px-6 py-2 rounded-lg font-bold transition-all ${this.dexMode==='pet' ? 'bg-indigo-600 text-white' : 'bg-gray-800 text-gray-400 hover:text-white'}">我的精灵</button>
            <button onclick="game.setDexMode('item')" class="px-6 py-2 rounded-lg font-bold transition-all ${this.dexMode==='item' ? 'bg-indigo-600 text-white' : 'bg-gray-800 text-gray-400 hover:text-white'}">我的道具</button>
        `;
        container.appendChild(tabContainer);

        if (this.dexMode === 'pet') {
            setTxt('dex-team-count', store.team.length);
            const ringKey = store.unlockedRings[store.unlockedRings.length - 1]; 
            setTxt('dex-team-max', RINGS[ringKey].slots);
            
            store.pets.forEach((p, idx) => {
                const s = SPECIES[p.id]; const inTeam = store.team.includes(String(p.uid));
                const div = document.createElement('div');
                div.className = `glass-panel-light p-4 relative group hover:bg-white/5 transition-all cursor-pointer ${inTeam ? 'border-indigo-500/50 bg-indigo-500/10' : ''}`;
                div.onclick = () => { store.activeIdx = idx; router.go('home'); };
                div.innerHTML = `<div class="aspect-square mb-4 relative">${getPetImage(p.id)}${inTeam ? `<div class="absolute top-0 right-0 bg-indigo-600 text-white text-[10px] px-2 py-0.5 rounded font-bold uppercase tracking-wider shadow-lg">出战</div>` : ''}</div><div class="text-center"><div class="font-bold text-white text-sm mb-1 truncate">${s.name}</div><div class="flex items-center justify-center gap-2 mb-2"><span class="text-[10px] px-1.5 py-0.5 rounded bg-gray-800 text-gray-400 border border-gray-700">Lv.${p.lvl}</span><span class="type-badge ${TYPES[s.type].color} text-[8px] px-1.5 py-0.5">${TYPES[s.type].name}</span></div>${inTeam ? `<button onclick="event.stopPropagation(); game.removeFromTeam('${p.uid}')" class="w-full py-1.5 bg-red-900/30 hover:bg-red-800/50 text-red-300 rounded text-xs border border-red-800/30 transition-colors">移出队伍</button>` : `<button onclick="event.stopPropagation(); game.addToTeam('${p.uid}')" class="w-full py-1.5 bg-indigo-900/30 hover:bg-indigo-800/50 text-indigo-300 rounded text-xs border border-indigo-800/30 transition-colors">加入队伍</button>`}</div>`;
                container.appendChild(div);
            });
        } else {
            const items = [
                { id: 'guide_book', name: '世界旅途指南', icon: '📖', desc: '记录了属性克制关系' },
                { id: 'potion', name: '回复药水', icon: '💊', desc: '恢复宠物体力' },
                { id: 'ball', name: '捕兽网', icon: '🕸️', desc: '捕捉野生宠物' },
                { id: 'xp_potion', name: '经验药水', icon: '🧪', desc: '增加 500 点经验值' },
                ...Object.values(RINGS).map(r => ({ id: 'ring', name: r.name, icon: r.icon, desc: r.desc }))
            ];
            
            items.forEach(item => {
                const count = store.inventory[item.id] || 0;
                const isRing = item.id === 'ring';
                const hasRing = isRing && store.unlockedRings.some(r => RINGS[r].name === item.name);
                
                if (count > 0 || hasRing) {
                    const div = document.createElement('div');
                    div.className = `glass-panel-light p-4 flex items-center gap-4`;
                    div.innerHTML = `<div class="text-3xl w-12 h-12 flex items-center justify-center bg-black/30 rounded-lg">${item.icon}</div>
                    <div class="flex-1">
                        <div class="font-bold text-white">${item.name}</div>
                        <div class="text-xs text-gray-500">${item.desc}</div>
                    </div>
                    ${!isRing ? `<div class="text-xl font-mono font-bold text-indigo-400">x${count}</div>` : '<div class="text-xs text-green-500 border border-green-500/30 px-2 py-1 rounded">永久</div>'}`;
                    
                    if (item.id === 'guide_book') { 
                        div.onclick = () => game.showGuideBook(); 
                        div.style.cursor = 'pointer'; 
                        div.classList.add('hover:bg-indigo-900/30', 'border-indigo-500/30'); 
                    }
                    container.appendChild(div);
                }
            });
        }
    },

    addToTeam(uid) {
        const ringKey = store.unlockedRings[store.unlockedRings.length - 1]; const maxSlots = RINGS[ringKey].slots;
        if (store.team.length >= maxSlots) return toast('队伍已满！请升级空间戒。');
        if (!store.team.includes(uid)) { store.team.push(uid); this.save(); this.renderDex(); this.updateHud(); toast('已加入队伍'); }
    },

    removeFromTeam(uid) {
        if (store.team.length <= 1) return toast('队伍中至少需要一只宠物！'); store.team = store.team.filter(id => id !== uid); this.save(); this.renderDex(); this.updateHud(); toast('已移出队伍');
    },

    renderPokedex() { this.togglePokedexTab('pet'); },
    togglePokedexTab(tab) { document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); $(`tab-${tab}`).classList.add('active'); if (tab === 'pet') { $('pokedex-grid-pet').classList.remove('hidden'); $('pokedex-grid-item').classList.add('hidden'); this.renderPokedexPets(); } else { $('pokedex-grid-pet').classList.add('hidden'); $('pokedex-grid-item').classList.remove('hidden'); this.renderPokedexItems(); } },
    renderPokedexPets() {
        const container = $('pokedex-grid-pet'); if(!container) return; container.innerHTML = ''; const unlockedCount = store.pokedex.length; setTxt('pokedex-count', unlockedCount);
        Object.keys(TYPES).forEach(type => {
            const section = document.createElement('div'); section.innerHTML = `<h3 class="text-xl font-bold text-white mb-6 flex items-center gap-3"><span class="w-3 h-8 rounded-full bg-gradient-to-b ${TYPES[type].color}"></span>${TYPES[type].name}系图鉴</h3>`;
            const grid = document.createElement('div'); grid.className = 'grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-6';
            Object.values(SPECIES).filter(s => s.type === type).forEach(s => {
                const sId = Object.keys(SPECIES).find(key => SPECIES[key] === s); const unlocked = store.pokedex.includes(sId);
                const card = document.createElement('div'); card.className = `glass-panel-light p-4 flex flex-col items-center gap-3 transition-all ${unlocked ? 'hover:bg-gray-800' : 'grayscale opacity-60 hover:opacity-80 hover:bg-gray-800'}`;
                card.innerHTML = `<div class="w-full aspect-square bg-black/20 rounded-lg p-2">${getPetImage(sId)}</div><div class="text-center"><div class="font-bold text-white text-sm">${s.name}</div><div class="text-[10px] text-gray-500 mt-1">No.${sId.split('_')[1].padStart(3, '0')}</div></div>`;
                card.onclick = () => showEvolutionChain(sId); card.style.cursor = 'pointer'; grid.appendChild(card);
            });
            section.appendChild(grid); container.appendChild(section);
        });
    },
    renderPokedexItems() {
        const container = $('pokedex-grid-item'); if(!container) return; container.innerHTML = '';
        const items = [
            { id: 'potion', name: '回复药水', icon: '💊', desc: '恢复宠物体力' },
            { id: 'ball', name: '捕兽网', icon: '🕸️', desc: '捕捉野生宠物' },
            { id: 'xp_potion', name: '经验药水', icon: '🧪', desc: '增加 500 点经验值' },
            { id: 'guide_book', name: '世界旅途指南', icon: '📖', desc: '记录了属性克制关系' },
            ...Object.values(RINGS).map(r => ({ id: 'ring', name: r.name, icon: r.icon, desc: r.desc }))
        ];
        items.forEach(item => {
            const has = store.inventory[item.id] > 0 || (item.id === 'ring' && store.unlockedRings.some(r => RINGS[r].name === item.name));
            const div = document.createElement('div'); div.className = `glass-panel-light p-4 flex items-center gap-4 ${has ? '' : 'opacity-40 grayscale'}`;
            div.innerHTML = `<div class="text-3xl w-12 h-12 flex items-center justify-center bg-black/30 rounded-lg">${item.icon}</div><div><div class="font-bold text-white">${item.name}</div><div class="text-xs text-gray-500">${item.desc}</div></div>`;
            if (item.id === 'guide_book' && has) { div.onclick = () => game.showGuideBook(); div.style.cursor = 'pointer'; div.classList.add('hover:bg-indigo-900/30', 'border-indigo-500/30'); }
            container.appendChild(div);
        });
    },
    showGuideBook() { $('guide-modal').classList.remove('hidden'); },
    showBigPreview(id) { const s = SPECIES[id]; const c = $('pet-preview-container'); if(c) c.innerHTML = getPetImage(id); setTxt('pet-preview-name', s.name); $('evo-modal').classList.add('hidden'); $('pet-preview-modal').classList.remove('hidden'); },
    showConfirm(msg, onConfirm) {
        const modal = $('custom-confirm-modal'); const txt = $('custom-confirm-msg'); const btnOk = $('custom-confirm-ok'); const btnCancel = $('custom-confirm-cancel');
        if(txt) txt.innerText = msg; 
        if(modal) modal.classList.remove('hidden');
        if(btnOk) {
            const newOk = btnOk.cloneNode(true); 
            btnOk.parentNode.replaceChild(newOk, btnOk);
            newOk.onclick = () => { modal.classList.add('hidden'); if (onConfirm) onConfirm(); };
        }
        if(btnCancel) {
            const newCancel = btnCancel.cloneNode(true);
            btnCancel.parentNode.replaceChild(newCancel, btnCancel);
            newCancel.onclick = () => { modal.classList.add('hidden'); };
        }
    },
    showAlert(msg) {
        const modal = $('custom-confirm-modal'); const txt = $('custom-confirm-msg'); const btnOk = $('custom-confirm-ok'); const btnCancel = $('custom-confirm-cancel');
        if(txt) txt.innerText = msg; 
        if(btnCancel) btnCancel.style.display = 'none'; 
        if(modal) modal.classList.remove('hidden');
        if(btnOk) {
            const newOk = btnOk.cloneNode(true); btnOk.parentNode.replaceChild(newOk, btnOk);
            newOk.onclick = () => { modal.classList.add('hidden'); btnCancel.style.display = 'block'; };
        }
    },
    
    // --- 新增：物品获得弹窗 ---
    showRewardModal(itemType, value) {
        const modal = $('reward-modal');
        if(!modal) return;
        
        let icon = '';
        let name = '';
        let desc = '';
        
        if (itemType === 'gold') {
            icon = '🪙';
            name = '金币';
            desc = `x${value}`;
        } else {
            // 简单的道具映射，可以扩展
            const itemMap = {
                'potion': { icon: '💊', name: '回复药水' },
                'ball': { icon: '🕸️', name: '捕兽网' },
                'xp_potion': { icon: '🧪', name: '经验药水' },
                'guide_book': { icon: '📖', name: '世界旅途指南' }
            };
            const item = itemMap[itemType] || { icon: '📦', name: '未知物品' };
            icon = item.icon;
            name = item.name;
            desc = `x${value}`;
        }
        
        $('reward-icon').innerText = icon;
        $('reward-name').innerText = name;
        $('reward-desc').innerText = desc;
        
        modal.classList.remove('hidden');
    },

    // --- 新增：战斗结算弹窗 ---
    showBattleResult(gold, xp, drops, onConfirm) {
        const modal = $('battle-result-modal');
        if(!modal) return;
        
        setTxt('res-gold', `+${gold}`);
        setTxt('res-xp', `+${xp} XP`);
        
        const dropContainer = $('res-drops');
        if(dropContainer) {
            if(drops.length > 0) {
                dropContainer.innerHTML = drops.map(d => `
                    <div class="flex items-center gap-3 bg-black/30 p-3 rounded-lg border border-gray-700">
                        <div class="text-2xl">${d.icon}</div>
                        <div>
                            <div class="text-sm font-bold text-white">${d.name}</div>
                            <div class="text-[10px] text-gray-400 uppercase tracking-widest">${d.type === 'pet' ? 'New Pet' : 'Item'}</div>
                        </div>
                    </div>
                `).join('');
                $('res-no-drop').classList.add('hidden');
                dropContainer.classList.remove('hidden');
            } else {
                dropContainer.classList.add('hidden');
                $('res-no-drop').classList.remove('hidden');
            }
        }
        
        const btn = $('res-confirm-btn');
        if(btn) {
            const newBtn = btn.cloneNode(true);
            btn.parentNode.replaceChild(newBtn, btn);
            newBtn.onclick = () => {
                modal.classList.add('hidden');
                if(onConfirm) onConfirm();
            };
        }
        
        modal.classList.remove('hidden');
    },
    
    showDevInfo() {
        $('dev-info-modal').classList.remove('hidden');
    },

    renderMenu() {
        const el = $('menu-options'); if(!el) return; el.innerHTML = '';
        
        const btnDev = document.createElement('button'); 
        btnDev.className = 'w-full bg-indigo-900/50 hover:bg-indigo-800 text-indigo-200 border border-indigo-700/50 p-4 rounded-xl flex items-center gap-4 transition-all mb-2'; 
        btnDev.innerHTML = `<span class="text-2xl">👨‍💻</span><div class="text-left"><div class="font-bold">关于开发者 (Credits)</div><div class="text-xs opacity-60">查看游戏作者信息</div></div>`; 
        btnDev.onclick = () => game.showDevInfo();
        el.appendChild(btnDev);
        
        const btnClear = document.createElement('button'); btnClear.className = 'w-full bg-red-900/50 hover:bg-red-800 text-red-200 border border-red-700/50 p-4 rounded-xl flex items-center gap-4 transition-all group'; btnClear.innerHTML = `<span class="text-2xl group-hover:scale-110 transition-transform">🗑️</span><div class="text-left"><div class="font-bold">清除存档 (Wipe Save)</div><div class="text-xs opacity-60">彻底删除所有进度并重启游戏</div></div>`; btnClear.onclick = () => { game.showConfirm('警告：这将永久删除你的所有进度！确定吗？', () => { game.wipeSave(); }); }; el.appendChild(btnClear);
        const btnFullscreen = document.createElement('button'); btnFullscreen.className = 'w-full bg-gray-800 hover:bg-gray-700 text-gray-200 border border-gray-700 p-4 rounded-xl flex items-center gap-4 transition-all'; btnFullscreen.innerHTML = `<span class="text-2xl">📺</span><div class="text-left"><div class="font-bold">全屏模式 (Fullscreen)</div><div class="text-xs opacity-60">点击切换/退出全屏</div></div>`; btnFullscreen.onclick = () => toggleFullScreen(); el.appendChild(btnFullscreen);
        const btnGod = document.createElement('button'); btnGod.className = 'w-full bg-indigo-900/30 hover:bg-indigo-800/50 text-indigo-200 border border-indigo-500/30 p-4 rounded-xl flex items-center gap-4 transition-all'; btnGod.innerHTML = `<span class="text-2xl">⚡</span><div class="text-left"><div class="font-bold">至高权限 (God Mode)</div><div class="text-xs opacity-60">输入密匙开启创世之力</div></div>`; btnGod.onclick = () => { $('god-modal').classList.remove('hidden'); $('god-password').value = ''; $('god-password').focus(); }; el.appendChild(btnGod);
        
        // 新增退出按钮
        const btnExit = document.createElement('button'); 
        btnExit.className = 'w-full bg-gray-800 hover:bg-gray-700 text-white border border-gray-700 p-4 rounded-xl flex items-center gap-4 transition-all mt-4'; 
        btnExit.innerHTML = `<span class="text-2xl">🚪</span><div class="text-left"><div class="font-bold">退出游戏 (Exit)</div><div class="text-xs opacity-60">返回开始界面</div></div>`; 
        btnExit.onclick = () => router.go('start');
        el.appendChild(btnExit);
    },
    
    wipeSave() { localStorage.removeItem('pk_evo_save'); localStorage.removeItem('pk_god_mode'); toast('存档已清除，正在重启...'); setTimeout(() => location.reload(), 1500); },
    activateGodMode(password) {
        if (password === '19167176661') {
            localStorage.setItem('pk_god_mode', 'true'); store.gold = 900000000; store.inventory.potion = 9999; store.inventory.ball = 9999; store.inventory.guide_book = 1; store.inventory.xp_potion = 9999;
            store.unlockedRings = ['ring_silver', 'ring_gold', 'ring_overlord']; store.unlockedAreas = ['meadow', 'volcano', 'beach', 'sky', 'graveyard', 'arena'];
            Object.keys(SPECIES).forEach(id => {
                if (!store.pokedex.includes(id)) store.pokedex.push(id);
                const alreadyHas = store.pets.some(p => p.id === id);
                if(!alreadyHas) {
                    const sData = SPECIES[id]; const base = sData.base || {hp:50, atk:10}; const growth = sData.growth || {hp:10, atk:2}; const lvl = 100;
                    const maxHp = Math.floor(base.hp + growth.hp * lvl); const atk = Math.floor(base.atk + growth.atk * lvl);
                    const uid = 'god_' + id + '_' + Date.now();
                    const newPet = { uid: uid, id: id, lvl: lvl, xp: 0, max_xp: 999999, hp: maxHp, max_hp: maxHp, atk: atk, bond: 100, status: null };
                    store.pets.push(newPet);
                }
            });
            this.save(); this.updateHud(); $('god-modal').classList.add('hidden');
            this.showAlert(`权限认证通过！\n获得创世资金与全图鉴神宠！\n系统正在重载进入创世者模式...`); setTimeout(() => { location.reload(); }, 2000); return true;
        } else { game.showAlert('❌ 密匙错误！权限拒绝。'); $('god-password').value = ''; $('god-password').focus(); return false; }
    }
};

function showEvolutionChain(sId) { 
    const parts = sId.split('_'); 
    const type = parts[0]; 
    const idNum = parseInt(parts[1]); 
    const familyStart = idNum <= 4 ? 1 : 5; 
    const familyEnd = idNum <= 4 ? 4 : 8; 
    
    const family = Object.keys(SPECIES).filter(k => { 
        const p = k.split('_'); 
        const n = parseInt(p[1]); 
        return p[0] === type && n >= familyStart && n <= familyEnd; 
    }).sort((a,b) => SPECIES[a].stage - SPECIES[b].stage); 
    
    const chainEl = $('evo-chain'); 
    if (chainEl) {
        chainEl.innerHTML = ''; 
        family.forEach(fid => { 
            const famS = SPECIES[fid]; 
            const div = document.createElement('div'); 
            div.className = "glass-panel-light p-6 flex flex-col items-center min-w-[240px] text-center cursor-pointer hover:bg-white/10 transition-all group"; 
            div.onclick = (e) => { 
                e.stopPropagation(); 
                game.showBigPreview(fid); 
            }; 
            div.innerHTML = `<div class="w-40 h-40 mb-6 transform group-hover:scale-110 transition-transform duration-300 drop-shadow-xl">${getPetImage(fid)}</div><div class="text-2xl font-bold text-white mb-2 tracking-wide">${famS.name}</div><div class="text-xs text-indigo-300 uppercase mt-1 tracking-widest bg-indigo-500/10 px-3 py-1 rounded-full border border-indigo-500/20">${famS.stage === 4 ? '究极体' : '阶段 ' + famS.stage}</div><p class="text-xs text-gray-400 mt-4 max-w-[180px] leading-relaxed border-t border-white/5 pt-3">${famS.desc || '暂无描述'}</p>`; 
            chainEl.appendChild(div); 
        }); 
        const modal = $('evo-modal');
        if(modal) modal.classList.remove('hidden'); 
    }
}
