// ==========================================
// PIXI INITIALISIERUNG (V8)
// ==========================================
let floorGraphic = null;
async function initPixi() {
    if (app) return;

    app = new PIXI.Application();

    // 1. Asynchrones Init (v8 Standard)
    await app.init({
        width: GAME_WIDTH,
        height: GAME_HEIGHT,
        backgroundColor: 0x1a1a1a, // Dunkelgrau
        preference: 'webgpu',      // Versuch WebGPU (schneller auf Handy!)
        resolution: Math.min(window.devicePixelRatio || 1, 2), // Retina Limit
        autoDensity: true,
        antialias: false,
        roundPixels: true          // Wichtig für Pixelart
    });

    // 2. Canvas einhängen
    document.getElementById('game-container').appendChild(app.canvas);

    // 3. Layer erstellen
    bgLayer = new PIXI.Container();
    gameLayer = new PIXI.Container();
    debugLayer = new PIXI.Graphics(); // Für Hitboxen

    // Sortierung aktivieren (damit Player vor Obstacles ist)
    gameLayer.sortableChildren = true;

    app.stage.addChild(bgLayer);
    app.stage.addChild(gameLayer);
    app.stage.addChild(debugLayer);

    // Einmalig Resizen
    resize();

    console.log(`🚀 Renderer: ${app.renderer.name}`);
}

function resize() {
    if (!app || !app.canvas) return;

    const windowWidth = window.innerWidth - 20;
    const windowHeight = window.innerHeight - 20;
    const targetRatio = GAME_WIDTH / GAME_HEIGHT;
    const windowRatio = windowWidth / windowHeight;

    let finalWidth, finalHeight;

    if (windowRatio < targetRatio) {
        finalWidth = windowWidth;
        finalHeight = windowWidth / targetRatio;
    } else {
        finalHeight = windowHeight;
        finalWidth = finalHeight * targetRatio;
    }

    // CSS Skalierung
    app.canvas.style.width = `${Math.floor(finalWidth)}px`;
    app.canvas.style.height = `${Math.floor(finalHeight)}px`;
}

window.addEventListener('resize', resize);


// ==========================================
// RENDER LOOP (RETAINED MODE)
// ==========================================

async function drawGame(alpha = 1.0) {
    if (!app) {
        if(!document.getElementById('game-container').querySelector('canvas')) await initPixi();
        return;
    }

    // 1. HINTERGRUND
    updateBackground();

    // 2. BODEN (FIX: Einmalig erstellen oder updaten)
    if (!floorGraphic) {
        floorGraphic = new PIXI.Graphics();
        bgLayer.addChild(floorGraphic); // Zum Background Layer hinzufügen
    }
    floorGraphic.clear();
    // Boden: Dunkelgrau
    floorGraphic.rect(0, GROUND_Y, GAME_WIDTH, 50).fill(0x333333);
    // Grüne Linie oben drauf (Gras/Teppich)
    floorGraphic.rect(0, GROUND_Y, GAME_WIDTH, 4).fill(0x4CAF50);


    // 3. OBJEKTE SYNCEN
    syncSprites(obstacles, spriteCache, 'obstacle', alpha);
    syncSprites(platforms, platformCache, 'platform', alpha);

    // 4. SPIELER
    updatePlayer(alpha);

    // 5. DEBUG
    if (typeof DEBUG_SYNC !== 'undefined' && DEBUG_SYNC) {
        drawDebugOverlay(alpha);
    } else {
        debugLayer.clear();
    }
}

// ------------------------------------------------------
// HELPER: SYNC SYSTEM
// ------------------------------------------------------
function syncSprites(dataList, cacheMap, type, alpha) {
    const usedObjects = new Set();

    dataList.forEach(obj => {
        usedObjects.add(obj);
        let sprite = cacheMap.get(obj);

        if (!sprite) {
            sprite = createPixiSprite(obj, type);
            gameLayer.addChild(sprite);
            cacheMap.set(obj, sprite);
        }

        const def = obj.def || {};

        const rX = (obj.prevX !== undefined) ? lerp(obj.prevX, obj.x, alpha) : obj.x;
        const rY = obj.y;

        if (obj.speech) {
            let bubble = sprite.children.find(c => c.label === "bubble");

            if (!bubble) {
                bubble = createSpeechBubble(obj.speech);
                bubble.y = -10;
                if (def.height) bubble.y = -5;

                sprite.addChild(bubble);
            }

        } else {
            // Keine Sprache mehr? Blase entfernen falls vorhanden
            const bubble = sprite.children.find(c => c.label === "bubble");
            if (bubble) {
                sprite.removeChild(bubble);
                bubble.destroy();
            }
        }

        if (type === 'platform') {
            sprite.x = rX;
            sprite.y = rY;
        } else {
            // Editor Werte
            const scale = def.imgScale || 1.0;
            const offX = def.imgOffsetX || 0;
            const offY = def.imgOffsetY || 0;
            const hbw = def.width || 30;
            const hbh = def.height || 30;

            const drawW = hbw * scale;
            const baseX = rX + (hbw - drawW) / 2;
            const baseY = rY + (hbh - (hbh * scale));

            sprite.x = baseX + offX;
            sprite.y = baseY + offY;
            sprite.width = drawW;
            sprite.height = hbh * scale;
        }
    });

    // C. Aufräumen (Garbage Collection)
    for (const [obj, sprite] of cacheMap.entries()) {
        if (!usedObjects.has(obj)) {
            gameLayer.removeChild(sprite);
            sprite.destroy();
            cacheMap.delete(obj);
        }
    }
}

function createPixiSprite(obj, type) {
    if (type === 'platform') {
        const g = new PIXI.Graphics();
        // Holz Plattform
        g.rect(0, 0, obj.w, obj.h).fill(0x8B4513); // Braun
        g.rect(0, 0, obj.w, 5).fill(0xA0522D);     // Hellbraun Oben
        return g;
    }
    else {
        const def = obj.def || {};

        // CHECK: Ist die Textur im Cache?
        // Wir nutzen PIXI.Assets.get(), das ist sicherer als cache.has
        let texture = null;
        try {
            if (def.id) texture = PIXI.Assets.get(def.id);
        } catch(e) {}

        if (texture) {
            const s = new PIXI.Sprite(texture);
            return s;
        } else {
            // FALLBACK (Wenn Bild fehlt -> Magenta Box)
            const g = new PIXI.Graphics();
            let color = 0xFF00FF;
            if (def.type === 'coin') color = 0xFFD700;

            g.rect(0, 0, def.width||30, def.height||30).fill(color);
            return g;
        }
    }
}

// ------------------------------------------------------
// PLAYER & BG
// ------------------------------------------------------
function updatePlayer(alpha) {
    if (!pixiPlayer) {
        if (PIXI.Assets.cache.has('player')) {
            pixiPlayer = PIXI.Sprite.from('player');
        } else {
            pixiPlayer = new PIXI.Graphics().rect(0,0,30,50).fill(0xFF0000);
        }
        gameLayer.addChild(pixiPlayer);
        pixiPlayer.zIndex = 100; // Immer im Vordergrund
    }

    let rY = lerp(player.prevY || player.y, player.y, alpha);
    const drawY = isCrouching ? rY + 25 : rY;

    pixiPlayer.x = player.x;
    pixiPlayer.y = drawY;
}

function updateBackground() {
    // FEHLERBEHEBUNG:
    // Wir prüfen 'gameConfig.backgrounds' statt 'bgSprites'
    if (!gameConfig || !gameConfig.backgrounds || gameConfig.backgrounds.length === 0) return;

    const changeInterval = 10000;
    const idx = Math.floor(score / changeInterval) % gameConfig.backgrounds.length;

    // Der Key ist der Dateiname (so haben wir es in main.js geladen)
    const bgKey = gameConfig.backgrounds[idx];

    // Sicherstellen, dass Asset geladen ist
    if (!PIXI.Assets.cache.has(bgKey)) return;

    if (!bgSprite) {
        bgSprite = new PIXI.Sprite();
        bgSprite.width = GAME_WIDTH;
        bgSprite.height = GAME_HEIGHT;
        bgLayer.addChild(bgSprite);
    }

    // Textur wechseln wenn nötig
    const tex = PIXI.Assets.get(bgKey);
    if (tex && bgSprite.texture !== tex) {
        bgSprite.texture = tex;
    }
}

// ------------------------------------------------------
// DEBUG
// ------------------------------------------------------
function drawDebugOverlay(alpha) {
    const g = debugLayer;
    g.clear();

    // Server (Cyan)
    if (serverObstacles) {
        serverObstacles.forEach(o => {
            g.rect(o.x, o.y, o.w, o.h).stroke({ width: 1, color: 0x00FFFF });
        });
    }

    // Client (Grün)
    obstacles.forEach(o => {
        const def = o.def || {};
        const rX = (o.prevX !== undefined) ? lerp(o.prevX, o.x, alpha) : o.x;
        g.rect(rX, o.y, def.width||30, def.height||30).stroke({ width: 1, color: 0x00FF00 });
    });
}

// Helper: Erstellt eine Pixi-Sprechblase
function createSpeechBubble(text) {
    const container = new PIXI.Container();

    // 1. Text erstellen
    const style = new PIXI.TextStyle({
        fontFamily: 'monospace',
        fontSize: 12,
        fontWeight: 'bold',
        fill: '#000000',
        align: 'center'
    });

    const pixiText = new PIXI.Text({ text: text, style: style });
    pixiText.anchor.set(0.5); // Text-Mitte ist Anker

    // Maße berechnen
    const w = pixiText.width + 10;
    const h = pixiText.height + 6;

    // 2. Hintergrund (Blase)
    const g = new PIXI.Graphics();
    g.rect(-w/2, -h/2, w, h).fill(0xFFFFFF); // Weißer Kasten
    g.rect(-w/2, -h/2, w, h).stroke({ width: 2, color: 0x000000 }); // Schwarzer Rand

    // Kleines Dreieck unten (optional, für den "Speech"-Look)
    g.moveTo(-5, h/2).lineTo(0, h/2 + 5).lineTo(5, h/2).fill(0xFFFFFF);

    // Zusammenfügen
    container.addChild(g);
    container.addChild(pixiText);

    // Name setzen, damit wir es später wiederfinden
    container.label = "bubble";

    return container;
}