// Terrain Generator System
// Generira proceduralni isometrični teren in skrbi za optimizacijo (Culling, Object Pooling)
class TerrainSystem {
    constructor(scene, width = 100, height = 100) {
        this.scene = scene;
        this.width = width;
        this.height = height;

        this.iso = new IsometricUtils(48, 24);
        this.noise = new PerlinNoise(Date.now());

        this.tiles = [];
        this.decorations = []; // Array za save/load compat
        this.decorationsMap = new Map(); // Fast lookup key->decor
        this.cropsMap = new Map(); // Store dynamic crops separately

        // Render state monitoring
        this.visibleTiles = new Map(); // Key: "x,y", Value: Sprite
        this.visibleDecorations = new Map(); // Key: "x,y", Value: Sprite
        this.visibleCrops = new Map(); // Key: "x,y", Value: Sprite

        this.offsetX = 0;
        this.offsetY = 0;

        // Object Pools
        this.tilePool = new ObjectPool(
            () => {
                const sprite = this.scene.add.image(0, 0, 'tile_grass');
                sprite.setOrigin(0.5, 0); // Isometrični tiles imajo origin zgoraj/center ali po potrebi
                return sprite;
            },
            (sprite) => {
                sprite.setVisible(true);
                sprite.setAlpha(1);
                sprite.clearTint();
            }
        );

        this.decorationPool = new ObjectPool(
            () => {
                const sprite = this.scene.add.sprite(0, 0, 'flower');
                sprite.setOrigin(0.5, 1);
                return sprite;
            },
            (sprite) => {
                sprite.setVisible(true);
                sprite.setAlpha(1);
                sprite.clearTint(); // Reset damage tint
            }
        );

        this.cropPool = new ObjectPool(
            () => {
                const sprite = this.scene.add.sprite(0, 0, 'crop_stage_1'); // Default texture logic needed
                sprite.setOrigin(0.5, 1);
                return sprite;
            },
            (sprite) => {
                sprite.setVisible(true);
                sprite.setAlpha(1);
            }
        );

        // Tipi terena z threshold vrednostmi + Y-LAYER STACKING
        this.terrainTypes = {
            WATER: { threshold: 0.3, color: 0x2166aa, name: 'water', texture: 'tile_water', yLayer: -1 },
            SAND: { threshold: 0.4, color: 0xf4e7c6, name: 'sand', texture: 'tile_sand', yLayer: 0 },

            // Y-LAYER GRASS VARIANTS (A, B, C systém)
            GRASS_FULL: { threshold: 0.50, color: 0x5cb85c, name: 'grass_full', texture: 'tile_grass_full', yLayer: 0 }, // A: Full grass
            GRASS_TOP: { threshold: 0.60, color: 0x5cb85c, name: 'grass_top', texture: 'tile_grass_top', yLayer: 1 }, // B: Grass top, dirt sides
            DIRT: { threshold: 0.75, color: 0x8b6f47, name: 'dirt', texture: 'tile_dirt', yLayer: 2 }, // C: Full dirt
            STONE: { threshold: 1.0, color: 0x7d7d7d, name: 'stone', texture: 'tile_stone', yLayer: 3 },

            PATH: { threshold: 999, color: 0x9b7653, name: 'path', texture: 'tile_path', yLayer: 0 }, // Pot/Road
            FARMLAND: { threshold: 999, color: 0x4a3c2a, name: 'farmland', texture: 'tile_farmland', yLayer: 0 }
        };
    }

    // Helper da dobi terrain type glede na elevation (Y-layer)
    getTerrainTypeByElevation(noiseValue, elevation) {
        // Osnovni terrain type iz noise
        let baseType = this.getTerrainType(noiseValue);

        // Če je grass, določi Y-layer variant glede na elevation
        if (baseType.name.includes('grass') || baseType === this.terrainTypes.GRASS_FULL ||
            baseType === this.terrainTypes.GRASS_TOP) {

            if (elevation > 0.7) {
                return this.terrainTypes.GRASS_FULL; // A: Najvišja plast (full grass)
            } else if (elevation > 0.4) {
                return this.terrainTypes.GRASS_TOP; // B: Srednja (grass top, dirt sides)
            } else {
                return this.terrainTypes.DIRT; // C: Nizka (full dirt)
            }
        }

        return baseType;
    }

    // Generiraj teksture za tiles (da ne uporabljamo Počasnih Graphics objektov)
    createTileTextures() {
        console.log('🎨 Creating tile textures...');

        for (const type of Object.values(this.terrainTypes)) {
            const key = `tile_${type.name}`;
            if (this.scene.textures.exists(key)) continue;

            // Check for custom grass tile
            if (type.name === 'grass' && this.scene.textures.exists('grass_tile')) {
                this.scene.textures.addImage(key, this.scene.textures.get('grass_tile').getSourceImage());
                type.texture = key;
                continue; // Skip procedural generation
            }

            const tileW = this.iso.tileWidth;
            const tileH = this.iso.tileHeight;
            const thickness = 8; // Minimal thickness - nearly 2D

            const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });

            // Helper for colors
            const baseColor = Phaser.Display.Color.IntegerToColor(type.color);
            let darkColor, darkerColor;

            // Y-LAYER STACKING: Different side colors based on layer
            if (type.name === 'grass_full') {
                // A: Full Grass Block - všechno zeleno
                darkColor = 0x5cb85c; // Green (lighter)
                darkerColor = 0x4a9d3f; // Green (darker)
            } else if (type.name === 'grass_top') {
                // B: Grass Top - zgoraj zeleno, stranice zemlja
                darkColor = 0x8b6f47; // Dirt color (brown)
                darkerColor = 0x5d4a2e; // Darker Dirt
            } else if (type.name === 'dirt') {
                // C: Full Dirt - vse rjavo
                darkColor = 0x8b6f47; // Dirt
                darkerColor = 0x654321; // Darker Dirt
            } else {
                // Standard block: Darken base color significantly
                darkColor = Phaser.Display.Color.IntegerToColor(type.color).darken(30).color;
                darkerColor = Phaser.Display.Color.IntegerToColor(type.color).darken(50).color;
            }

            // 1. Draw LEFT Side (Darker) - Minecraft volumetric effect
            graphics.fillStyle(darkColor, 1);
            graphics.beginPath();
            graphics.moveTo(0, tileH / 2); // Left Corner
            graphics.lineTo(tileW / 2, tileH); // Bottom Corner
            graphics.lineTo(tileW / 2, tileH + thickness); // Bottom Corner (Lowered)
            graphics.lineTo(0, tileH / 2 + thickness); // Left Corner (Lowered)
            graphics.closePath();
            graphics.fillPath();

            // 2. Draw RIGHT Side (Darkest) - Strong shadow
            graphics.fillStyle(darkerColor, 1);
            graphics.beginPath();
            graphics.moveTo(tileW / 2, tileH); // Bottom Corner
            graphics.lineTo(tileW, tileH / 2); // Right Corner
            graphics.lineTo(tileW, tileH / 2 + thickness); // Right Corner (Lowered)
            graphics.lineTo(tileW / 2, tileH + thickness); // Bottom Corner (Lowered)
            graphics.closePath();
            graphics.fillPath();

            // 3. Draw TOP Surface (bright)
            graphics.fillStyle(type.color, 1);
            graphics.beginPath();
            graphics.moveTo(tileW / 2, 0); // Top
            graphics.lineTo(tileW, tileH / 2); // Right
            graphics.lineTo(tileW / 2, tileH); // Bottom
            graphics.lineTo(0, tileH / 2); // Left
            graphics.closePath();
            graphics.fillPath();

            // 4. Add Minecraft-style texture pattern on top
            if (type.name === 'grass_full' || type.name === 'grass_top') {
                // Grass texture: Random pixel pattern
                graphics.fillStyle(0x4a9d3f, 0.3); // Slightly darker green
                for (let i = 0; i < 8; i++) {
                    const px = Math.random() * tileW;
                    const py = Math.random() * tileH;
                    graphics.fillRect(px, py, 2, 2);
                }
            } else if (type.name === 'dirt') {
                // Dirt texture: Darker spots
                graphics.fillStyle(0x6d5838, 0.4);
                for (let i = 0; i < 6; i++) {
                    const px = Math.random() * tileW;
                    const py = Math.random() * tileH;
                    graphics.fillRect(px, py, 3, 3);
                }
            } else if (type.name === 'stone') {
                // Stone texture: Gray spots
                graphics.fillStyle(0x666666, 0.3);
                for (let i = 0; i < 10; i++) {
                    const px = Math.random() * tileW;
                    const py = Math.random() * tileH;
                    graphics.fillRect(px, py, 2, 1);
                }
            } else if (type.name === 'path') {
                // Path texture: Small gravel stones
                graphics.fillStyle(0x7a5e42, 0.5); // Darker brown
                for (let i = 0; i < 12; i++) {
                    const px = Math.random() * tileW;
                    const py = Math.random() * tileH;
                    graphics.fillRect(px, py, 2, 2);
                }
            }

            // 5. Crisp black outline for block definition
            graphics.lineStyle(1, 0x000000, 0.3);
            graphics.strokePath();

            // Generate texture
            graphics.generateTexture(key, tileW, tileH + thickness);
            graphics.destroy();

            // Update texture name in type def
            type.texture = key;
        }
    }

    createGravestoneSprite() {
        // Extract gravestone from objects_pack (approx position in atlas)
        // Gravestone appears to be around position row 4, column 4-5 in the pack
        const canvas = document.createElement('canvas');
        const size = 32; // Approximate sprite size
        canvas.width = size;
        canvas.height = size;
        const ctx = canvas.getContext('2d', { willReadFrequently: true });

        const sourceTexture = this.scene.textures.get('objects_pack');
        const sourceImg = sourceTexture.getSourceImage();

        // Extract gravestone (cross tombstone) - estimated coords
        // Adjust these values based on actual sprite sheet layout
        const sourceX = 240; // Approximate X position
        const sourceY = 160; // Approximate Y position

        ctx.drawImage(sourceImg, sourceX, sourceY, size, size, 0, 0, size, size);

        // Create texture
        this.scene.textures.addCanvas('gravestone', canvas);
        console.log('✅ Gravestone sprite extracted!');
    }

    // Generiraj teren (data only)
    generate() {
        console.log(`🌍 Generating terrain data: ${this.width}x${this.height}...`);

        // Zagotovi teksture
        this.createTileTextures();

        // Zagotovi decoration teksture - check for custom sprites first
        if (!this.scene.textures.exists('flower')) {
            TextureGenerator.createFlowerSprite(this.scene, 'flower');
        }

        // Bush - use custom stone sprite if available
        if (this.scene.textures.exists('stone_sprite')) {
            // Use stone_sprite for bushes (rocks)
            if (!this.scene.textures.exists('bush')) {
                this.scene.textures.addImage('bush', this.scene.textures.get('stone_sprite').getSourceImage());
            }
        } else if (!this.scene.textures.exists('bush')) {
            TextureGenerator.createBushSprite(this.scene, 'bush');
        }

        // Tree - use custom tree sprite if available
        if (this.scene.textures.exists('tree_sprite')) {
            if (!this.scene.textures.exists('tree')) {
                this.scene.textures.addImage('tree', this.scene.textures.get('tree_sprite').getSourceImage());
            }
        } else if (!this.scene.textures.exists('tree')) {
            TextureGenerator.createTreeSprite(this.scene, 'tree');
        }

        // Gravestone - extract from objects_pack
        if (this.scene.textures.exists('objects_pack') && !this.scene.textures.exists('gravestone')) {
            this.createGravestoneSprite();
        }

        // Crop textures
        for (let i = 1; i <= 4; i++) {
            if (!this.scene.textures.exists(`crop_stage_${i}`))
                TextureGenerator.createCropSprite(this.scene, `crop_stage_${i}`, i);
        }

        this.decorationsMap.clear();
        this.decorations = [];
        this.cropsMap.clear();

        // Generiraj tile podatke
        for (let y = 0; y < this.height; y++) {
            this.tiles[y] = [];
            for (let x = 0; x < this.width; x++) {
                const noiseValue = this.noise.getNormalized(x, y, 0.05, 4);

                // Elevation (druga Perlin noise layer za hribe)
                let elevation = this.noise.getNormalized(x, y, 0.03, 3);

                // Get terrain type based on BOTH noise and elevation (Y-layer)
                let terrainType = this.getTerrainTypeByElevation(noiseValue, elevation);

                // === PATH GENERATION ===
                // Use a separate noise layer for paths (higher frequency for winding roads)
                const pathNoise = this.noise.getNormalized(x, y, 0.08, 2);

                // Create minimal paths - if noise is in a very specific narrow band
                // Avoid water (0.3 threshold) and edges
                if (pathNoise > 0.48 && pathNoise < 0.52 && noiseValue > 0.35) {
                    terrainType = this.terrainTypes.PATH;
                }

                // === FLOATING ISLAND EDGE === 
                const edgeDistance = 2; // Tiles from edge (tighter border)
                const isNearEdge = x < edgeDistance || x >= this.width - edgeDistance ||
                    y < edgeDistance || y >= this.height - edgeDistance;

                const isEdge = x === 0 || x === this.width - 1 ||
                    y === 0 || y === this.height - 1;

                // Override terrain type at edges
                if (isEdge) {
                    terrainType = this.terrainTypes.STONE; // Cliff wall (stone edge)
                } else if (isNearEdge) {
                    // Keep Y-layer system active
                }

                // Flatten edges (cliff drop-off for floating island effect)
                if (isEdge) {
                    elevation = 0; // Flat cliff wall
                } else if (isNearEdge) {
                    elevation = Math.max(0, elevation - 0.2); // Slight dip near edge
                }

                this.tiles[y][x] = {
                    gridX: x,
                    gridY: y,
                    type: terrainType.name,
                    texture: terrainType.texture,
                    height: noiseValue,
                    elevation: elevation, // 0-1 (0=low, 1=high)
                    yLayer: terrainType.yLayer, // Y-stacking layer
                    hasDecoration: false,
                    hasCrop: false
                };

                // Generacija dekoracij (shranimo v data, ne ustvarjamo sprite-ov še)
                if (x > 5 && x < this.width - 5 && y > 5 && y < this.height - 5) {
                    let decorType = null;
                    let maxHp = 1;
                    let scale = 1.0; // Default scale

                    if (terrainType.name.includes('grass')) { // Check ANY grass type
                        const rand = Math.random();

                        // Na hribih več kamnov
                        if (elevation > 0.6 && rand < 0.05) {
                            decorType = 'bush'; // Kamni
                            maxHp = 5;
                        } else if (rand < 0.025) { // Reduced to 2.5% trees (optimum balance)
                            decorType = 'tree';
                            maxHp = 5;

                            // TREE SIZING LOGIC
                            // 20% Normal (1.0)
                            // 60% Medium (0.6-0.8)
                            // 20% Tiny (0.2)
                            const sizeRand = Math.random();
                            if (sizeRand < 0.2) {
                                scale = 0.25; // 20% Tiny (0.25 visible enough)
                            } else if (sizeRand < 0.8) {
                                scale = 0.6 + Math.random() * 0.2; // 60% Scale 0.6-0.8
                            } else {
                                scale = 1.0; // 20% Full size
                            }

                        } else if (rand < 0.03) {
                            decorType = 'gravestone'; // 💀 Nagrobniki
                            maxHp = 10; // Težje uničiti
                        } else if (rand < 0.08) {
                            decorType = 'flower';
                            maxHp = 1;
                        }
                    } else if (terrainType.name === 'dirt' && Math.random() < 0.02) {
                        decorType = 'bush';
                        maxHp = 3;
                    }

                    if (decorType) {
                        const key = `${x},${y}`;
                        const decorData = {
                            gridX: x,
                            gridY: y,
                            type: decorType,
                            id: key,
                            maxHp: maxHp,
                            hp: maxHp,
                            scale: scale // Save scale
                        };

                        this.decorations.push(decorData);
                        this.decorationsMap.set(key, decorData);

                        this.tiles[y][x].hasDecoration = true;
                    }
                }
            }
        }

        console.log('✅ Terrain and decorations data generated!');
    }

    // DAMAGE / INTERACTION LOGIC
    damageDecoration(x, y, amount) {
        const key = `${x},${y}`;
        const decor = this.decorationsMap.get(key);

        if (!decor) return false;

        decor.hp -= amount;

        // Visual feedback (flash red)
        if (this.visibleDecorations.has(key)) {
            const sprite = this.visibleDecorations.get(key);
            sprite.setTint(0xff0000);
            this.scene.time.delayedCall(100, () => sprite.clearTint());

            // Shake effect?
            this.scene.tweens.add({
                targets: sprite,
                x: sprite.x + 2,
                duration: 50,
                yoyo: true,
                repeat: 1
            });
        }

        if (decor.hp <= 0) {
            this.removeDecoration(x, y);
            return 'destroyed';
        }

        return 'hit';
    }

    removeDecoration(x, y) {
        const key = `${x},${y}`;
        const decor = this.decorationsMap.get(key);

        if (!decor) return;

        // Remove visual
        if (this.visibleDecorations.has(key)) {
            const sprite = this.visibleDecorations.get(key);
            sprite.setVisible(false);
            this.decorationPool.release(sprite);
            this.visibleDecorations.delete(key);
        }

        // Remove data
        this.decorationsMap.delete(key);

        // Remove from array (slow but needed for save compat for now)
        const index = this.decorations.indexOf(decor);
        if (index > -1) this.decorations.splice(index, 1);

        // Update tile flag
        if (this.tiles[y] && this.tiles[y][x]) {
            this.tiles[y][x].hasDecoration = false;
        }

        return decor.type; // Return type for dropping loot
    }

    placeStructure(x, y, structureType) {
        if (this.decorationsMap.has(`${x},${y}`)) return false;

        const decorData = {
            gridX: x,
            gridY: y,
            type: structureType, // 'struct_fence', etc.
            id: `${x},${y}`,
            maxHp: 5,
            hp: 5
        };

        // Add to data
        this.decorations.push(decorData);
        this.decorationsMap.set(decorData.id, decorData);

        // Update tile
        const tile = this.getTile(x, y);
        if (tile) tile.hasDecoration = true;

        // Force Visual Update immediately? 
        // updateCulling will catch it on next frame, but to be safe:
        // Or leave it to update loop.

        return true;
    }

    // --- Dynamic Tile Modification ---

    setTileType(x, y, typeName) {
        if (!this.tiles[y] || !this.tiles[y][x]) return;

        const typeDef = Object.values(this.terrainTypes).find(t => t.name === typeName);
        if (!typeDef) return;

        this.tiles[y][x].type = typeName;
        this.tiles[y][x].texture = typeDef.texture;

        // Force visual update if visible
        const key = `${x},${y}`;
        if (this.visibleTiles.has(key)) {
            const sprite = this.visibleTiles.get(key);
            sprite.setTexture(typeDef.texture);
        }
    }

    addCrop(x, y, cropData) {
        const key = `${x},${y}`;
        this.cropsMap.set(key, cropData);
        this.tiles[y][x].hasCrop = true;
        // updateCulling loop will pick it up on next frame
    }

    removeCrop(x, y) {
        const key = `${x},${y}`;
        if (this.cropsMap.has(key)) {
            // Remove visual
            if (this.visibleCrops.has(key)) {
                const sprite = this.visibleCrops.get(key);
                sprite.setVisible(false);
                this.cropPool.release(sprite);
                this.visibleCrops.delete(key);
            }
            this.cropsMap.delete(key);
            this.tiles[y][x].hasCrop = false;
        }
    }

    updateCropVisual(x, y, stage) {
        const key = `${x},${y}`;
        if (this.visibleCrops.has(key)) {
            const sprite = this.visibleCrops.get(key);
            sprite.setTexture(`crop_stage_${stage}`);
        }
    }

    // Initialize rendering (called once)
    init(offsetX, offsetY) {
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

    // Update culling (called every frame)
    updateCulling(camera) {
        const view = camera.worldView;
        const buffer = 200;
        const left = view.x - buffer - this.offsetX;
        const top = view.y - buffer - this.offsetY;
        const right = view.x + view.width + buffer - this.offsetX;
        const bottom = view.y + view.height + buffer - this.offsetY;

        // Calculate visible bounding box (rough)
        const p1 = this.iso.toGrid(left, top);
        const p2 = this.iso.toGrid(right, top);
        const p3 = this.iso.toGrid(left, bottom);
        const p4 = this.iso.toGrid(right, bottom);

        const minGridX = Math.floor(Math.min(p1.x, p2.x, p3.x, p4.x));
        const maxGridX = Math.ceil(Math.max(p1.x, p2.x, p3.x, p4.x));
        const minGridY = Math.floor(Math.min(p1.y, p2.y, p3.y, p4.y));
        const maxGridY = Math.ceil(Math.max(p1.y, p2.y, p3.y, p4.y));

        const startX = Math.max(0, minGridX);
        const endX = Math.min(this.width, maxGridX);
        const startY = Math.max(0, minGridY);
        const endY = Math.min(this.height, maxGridY);

        const neededKeys = new Set();
        const neededDecorKeys = new Set();
        const neededCropKeys = new Set();

        for (let y = startY; y < endY; y++) {
            for (let x = startX; x < endX; x++) {
                const key = `${x},${y}`;
                neededKeys.add(key);

                // Tile Logic
                if (!this.visibleTiles.has(key)) {
                    const tilePos = this.iso.toScreen(x, y);
                    const tileData = this.tiles[y][x];

                    const sprite = this.tilePool.get();
                    sprite.setTexture(tileData.texture);

                    // Elevation effect: MOČAN vertikalni offset za hribe
                    const elevationOffset = tileData.elevation * -25; // Povečano iz -10 na -25
                    sprite.setPosition(
                        tilePos.x + this.offsetX,
                        tilePos.y + this.offsetY + elevationOffset
                    );

                    // DRAMATIČNO senčenje glede na višino
                    if (tileData.type === 'grass') {
                        let brightness = 1.0;

                        if (tileData.elevation > 0.5) {
                            // Visoko = svetlo (1.0 - 1.5)
                            brightness = 1.0 + (tileData.elevation - 0.5) * 1.0;
                        } else {
                            // Nizko = temno (0.7 - 1.0)
                            brightness = 0.7 + tileData.elevation * 0.6;
                        }

                        sprite.setTint(Phaser.Display.Color.GetColor(
                            Math.min(255, Math.floor(92 * brightness)),
                            Math.min(255, Math.floor(184 * brightness)),
                            Math.min(255, Math.floor(92 * brightness))
                        ));
                    }

                    sprite.setDepth(this.iso.getDepth(x, y) - 2000); // Tiles always in background

                    this.visibleTiles.set(key, sprite);
                }

                // Elevation effect matching tile logic
                const tileData = this.tiles[y][x];
                const elevationOffset = tileData.elevation * -25;

                // Crop Logic
                if (this.tiles[y][x].hasCrop) {
                    neededCropKeys.add(key);
                    if (!this.visibleCrops.has(key)) {
                        const cropData = this.cropsMap.get(key);
                        if (cropData) {
                            const cropPos = this.iso.toScreen(x, y);
                            const sprite = this.cropPool.get();
                            sprite.setTexture(`crop_stage_${cropData.stage}`);
                            sprite.setPosition(
                                cropPos.x + this.offsetX,
                                cropPos.y + this.offsetY + this.iso.tileHeight / 2 + elevationOffset
                            );
                            // Crop depth = Y pos
                            const depth = this.iso.getDepth(x, y);
                            sprite.setDepth(depth);

                            this.visibleCrops.set(key, sprite);
                        }
                    }
                }

                // Decoration Logic
                if (this.tiles[y][x].hasDecoration) {
                    neededDecorKeys.add(key);

                    if (!this.visibleDecorations.has(key)) {
                        // Fast lookup from map
                        const decor = this.decorationsMap.get(key);

                        if (decor) {
                            const decorPos = this.iso.toScreen(x, y);
                            const sprite = this.decorationPool.get();
                            sprite.setTexture(decor.type);

                            // Apply same elevation offset as tile
                            sprite.setPosition(
                                decorPos.x + this.offsetX,
                                decorPos.y + this.offsetY + this.iso.tileHeight / 2 + elevationOffset
                            );

                            const depth = this.iso.getDepth(x, y);
                            // Depth strategy: Base of object sorting.
                            // Add small offset based on type if needed, but mainly use Y
                            sprite.setDepth(depth);

                            // Apply scale if present
                            if (decor.scale) sprite.setScale(decor.scale);
                            else sprite.setScale(1);

                            sprite.flipX = (x + y) % 2 === 0;

                            // INTERACTIVITY FIX: Allow clicking sprites directly
                            sprite.setInteractive({ pixelPerfect: true, useHandCursor: true });

                            // Clear old listeners
                            sprite.off('pointerdown');
                            // Add click listener
                            sprite.on('pointerdown', (pointer) => {
                                if (this.scene.interactionSystem) {
                                    // Manually trigger interaction logic
                                    this.scene.interactionSystem.handleDecorationClick(x, y);
                                }
                            });

                            this.visibleDecorations.set(key, sprite);
                        }
                    }
                }
            }
        }

        // Cleanup invisible tiles
        for (const [key, sprite] of this.visibleTiles) {
            if (!neededKeys.has(key)) {
                sprite.setVisible(false);
                this.tilePool.release(sprite);
                this.visibleTiles.delete(key);
            }
        }

        // Cleanup invisible decorations
        for (const [key, sprite] of this.visibleDecorations) {
            if (!neededDecorKeys.has(key)) {
                sprite.setVisible(false);
                this.decorationPool.release(sprite);
                this.visibleDecorations.delete(key);
            }
        }

        // Cleanup visible crops
        for (const [key, sprite] of this.visibleCrops) {
            if (!neededCropKeys.has(key)) {
                sprite.setVisible(false);
                this.cropPool.release(sprite);
                this.visibleCrops.delete(key);
            }
        }
    }

    // Helper functions
    getTerrainType(value) {
        for (const type of Object.values(this.terrainTypes)) {
            if (value < type.threshold) {
                return type;
            }
        }
        return this.terrainTypes.STONE;
    }

    getTile(gridX, gridY) {
        if (gridX >= 0 && gridX < this.width && gridY >= 0 && gridY < this.height) {
            return this.tiles[gridY][gridX];
        }
        return null;
    }
}
