// Enhanced Map Editor with Zoom, Pan, Connections, and Live Stats
let currentLocations = [];
let availableNPCs = [];
let availableItems = [];
let availableInteractables = [];
let selectedLocationId = null;
let selectedNPCId = null;
let selectedItemId = null;
let selectedInteractableId = null;
let connections = [];
let liveStats = {players: {}, enemies: {}};
let canvas, ctx;
let currentTab = 'locations';

// View state
let scale = 50;
let minScale = 10;
let maxScale = 200;
let offsetX = 0;
let offsetY = 0;
let isDragging = false;
let dragStartX = 0;
let dragStartY = 0;
let clickStartTime = 0;
let clickStartPos = {x: 0, y: 0};

// Live stats refresh
let liveStatsInterval = null;

// Check authentication on load
window.addEventListener('DOMContentLoaded', async () => {
    const response = await fetch('/api/check-auth');
    const data = await response.json();
    
    if (data.authenticated) {
        showEditor();
    } else {
        document.getElementById('loginContainer').style.display = 'flex';
    }
});

// Ensure canvas is properly sized after everything loads
window.addEventListener('load', () => {
    if (canvas) {
        setTimeout(resizeCanvas, 100);
    }
});

// Login form handler
document.getElementById('loginForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    const password = document.getElementById('password').value;
    
    try {
        const response = await fetch('/api/login', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({password})
        });
        
        const data = await response.json();
        
        if (data.success) {
            showEditor();
        } else {
            showError(data.message);
        }
    } catch (error) {
        showError('Login failed: ' + error.message);
    }
});

function showError(message) {
    const errorDiv = document.getElementById('loginError');
    errorDiv.textContent = message;
    errorDiv.style.display = 'block';
}

function showSuccess(message) {
    const successDiv = document.getElementById('saveSuccess');
    successDiv.textContent = message;
    successDiv.style.display = 'block';
    setTimeout(() => {
        successDiv.style.display = 'none';
    }, 3000);
}

async function showEditor() {
    document.getElementById('loginContainer').style.display = 'none';
    document.getElementById('editorContainer').style.display = 'flex';
    
    // Initialize canvas
    canvas = document.getElementById('editorCanvas');
    ctx = canvas.getContext('2d');
    
    // Load data
    await loadLocations();
    await loadConnections();
    await loadAvailableNPCs();
    await loadAvailableInteractablesForLocations(); // Load interactables for location instances
    await loadAvailableItemsForLocations(); // Load items for interactable rewards
    await loadLiveStats();
    
    // Resize canvas after everything is loaded and rendered
    setTimeout(() => {
        resizeCanvas();
        window.addEventListener('resize', resizeCanvas);
    }, 100);
    
    // Start live stats refresh (every 5 seconds)
    liveStatsInterval = setInterval(loadLiveStats, 5000);
    
    // Draw map
    drawMap();
    
    // Canvas event handlers
    canvas.addEventListener('mousedown', handleMouseDown);
    canvas.addEventListener('mousemove', handleMouseMove);
    canvas.addEventListener('mouseup', handleMouseUp);
    canvas.addEventListener('wheel', handleWheel, {passive: false});
    canvas.addEventListener('mouseleave', () => { isDragging = false; });
}

function resizeCanvas() {
    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;
    drawMap();
}

async function loadLocations() {
    try {
        const response = await fetch('/api/editor/locations', {
            credentials: 'same-origin'
        });
        const data = await response.json();
        currentLocations = data.locations;
        renderLocationList();
        // Trigger resize after locations are rendered
        setTimeout(resizeCanvas, 50);
    } catch (error) {
        console.error('Failed to load locations:', error);
    }
}

async function loadConnections() {
    try {
        const response = await fetch('/api/editor/connections', {
            credentials: 'same-origin'
        });
        const data = await response.json();
        connections = data.connections;
        console.log('Loaded connections:', connections.length);
    } catch (error) {
        console.error('Failed to load connections:', error);
    }
}

async function loadAvailableNPCs() {
    try {
        const response = await fetch('/api/editor/available-npcs', {
            credentials: 'same-origin'
        });
        const data = await response.json();
        availableNPCs = data.npcs;
    } catch (error) {
        console.error('Failed to load NPCs:', error);
    }
}

async function loadLiveStats() {
    try {
        const response = await fetch('/api/editor/live-stats', {
            credentials: 'same-origin'
        });
        if (!response.ok) {
            console.error('Live stats request failed:', response.status);
            return;
        }
        const data = await response.json();
        liveStats.players = data.players_by_location || {};
        liveStats.enemies = data.enemies_by_location || {};
        drawMap(); // Redraw to show updated stats
    } catch (error) {
        console.error('Failed to load live stats:', error);
    }
}

function renderLocationList() {
    const list = document.getElementById('locationList');
    list.innerHTML = '';
    
    currentLocations.forEach(location => {
        const item = document.createElement('div');
        item.className = 'location-item';
        item.dataset.name = location.name;
        item.dataset.id = location.id;
        if (location.id === selectedLocationId) {
            item.classList.add('active');
        }
        
        const playerCount = liveStats.players[location.id] || 0;
        const enemyCount = liveStats.enemies[location.id] || 0;
        
        item.innerHTML = `
            <div class="location-item-name">${location.name}</div>
            <div class="location-item-coords">📍 (${location.x}, ${location.y}) | Danger: ${location.danger_level}</div>
            ${playerCount > 0 || enemyCount > 0 ? `<div class="location-item-stats">👥 ${playerCount} | 👹 ${enemyCount}</div>` : ''}
        `;
        
        item.onclick = () => selectLocation(location.id);
        list.appendChild(item);
    });
}

async function selectLocation(locationId) {
    selectedLocationId = locationId;
    renderLocationList();
    
    // Load full location details
    try {
        const response = await fetch(`/api/editor/location/${locationId}`);
        const location = await response.json();
        populateForm(location);
    } catch (error) {
        console.error('Failed to load location details:', error);
    }
    
    drawMap();
}

function populateForm(location) {
    document.getElementById('noSelectionMessage').classList.add('hidden');
    document.getElementById('propertiesForm').classList.remove('hidden');
    
    document.getElementById('locationId').value = location.id;
    document.getElementById('locationName').value = location.name;
    document.getElementById('locationDescription').value = location.description;
    document.getElementById('locationX').value = location.x;
    document.getElementById('locationY').value = location.y;
    document.getElementById('dangerLevel').value = location.danger_level;
    document.getElementById('encounterRate').value = location.encounter_rate;
    document.getElementById('wanderingChance').value = location.wandering_chance;
    document.getElementById('imagePath').value = location.image_path || '';
    
    // Update image preview
    updateImagePreview(location.image_path);
    
    // Render spawn list
    renderSpawnList(location.spawn_npcs);
    
    // Render interactables list
    renderInteractablesList(location.interactables || {});
    
    // Render connections
    renderConnectionsList(location.id, location.exits);
}

function updateImagePreview(imagePath) {
    const preview = document.getElementById('imagePreview');
    if (imagePath) {
        preview.innerHTML = `<img src="/${imagePath}" alt="Location image">`;
    } else {
        preview.innerHTML = '<span>No image</span>';
    }
}

function renderSpawnList(spawns) {
    const list = document.getElementById('spawnList');
    list.innerHTML = '';
    
    spawns.forEach((spawn, index) => {
        const item = document.createElement('div');
        item.className = 'spawn-item';
        item.innerHTML = `
            <div class="spawn-item-info">
                <div class="spawn-item-name">${spawn.emoji} ${spawn.name}</div>
                <div class="spawn-item-weight">Weight: ${spawn.weight}</div>
            </div>
            <button class="btn btn-remove" onclick="removeSpawn(${index})">Remove</button>
        `;
        list.appendChild(item);
    });
}

function renderConnectionsList(locationId, exits) {
    const list = document.getElementById('connectionsList');
    if (!list) return;
    
    list.innerHTML = '';
    
    for (const [direction, destId] of Object.entries(exits)) {
        const destLocation = currentLocations.find(l => l.id === destId);
        if (destLocation) {
            const item = document.createElement('div');
            item.className = 'connection-item';
            item.innerHTML = `
                <div class="connection-info">
                    <div class="connection-direction">${direction} → ${destLocation.name}</div>
                </div>
                <button class="btn btn-remove" onclick="deleteConnection('${locationId}', '${destId}')">×</button>
            `;
            list.appendChild(item);
        }
    }
}

// ==================== CANVAS DRAWING ====================

function drawMap() {
    if (!ctx) return;
    
    // Clear canvas
    ctx.fillStyle = '#0f0f1e';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    
    const centerX = canvas.width / 2 + offsetX;
    const centerY = canvas.height / 2 + offsetY;
    
    // Draw grid
    drawGrid(centerX, centerY);
    
    // Draw connections first (under locations)
    drawConnections(centerX, centerY);
    
    // Draw locations
    drawLocations(centerX, centerY);
    
    // Draw zoom indicator
    ctx.fillStyle = '#e0e0e0';
    ctx.font = '12px monospace';
    ctx.textAlign = 'left';
    ctx.fillText(`Zoom: ${Math.round(scale)}px/unit`, 10, 20);
}

function drawGrid(centerX, centerY) {
    ctx.strokeStyle = '#1a1a3e';
    ctx.lineWidth = 1;
    
    // Vertical lines
    for (let x = centerX % scale; x < canvas.width; x += scale) {
        ctx.beginPath();
        ctx.moveTo(x, 0);
        ctx.lineTo(x, canvas.height);
        ctx.stroke();
    }
    
    // Horizontal lines
    for (let y = centerY % scale; y < canvas.height; y += scale) {
        ctx.beginPath();
        ctx.moveTo(0, y);
        ctx.lineTo(canvas.width, y);
        ctx.stroke();
    }
    
    // Draw axes
    ctx.strokeStyle = '#3a3a6a';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(centerX, 0);
    ctx.lineTo(centerX, canvas.height);
    ctx.stroke();
    
    ctx.beginPath();
    ctx.moveTo(0, centerY);
    ctx.lineTo(canvas.width, centerY);
    ctx.stroke();
}

function drawConnections(centerX, centerY) {
    console.log('Drawing connections, total:', connections.length);
    connections.forEach(conn => {
        const fromLoc = currentLocations.find(l => l.id === conn.from);
        const toLoc = currentLocations.find(l => l.id === conn.to);
        
        if (fromLoc && toLoc) {
            const x1 = centerX + fromLoc.x * scale;
            const y1 = centerY - fromLoc.y * scale;
            const x2 = centerX + toLoc.x * scale;
            const y2 = centerY - toLoc.y * scale;
            
            // Draw arrow
            ctx.strokeStyle = '#00bcd4'; // Cyan color to avoid confusion with axes
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.stroke();
            
            // Draw arrowhead
            const angle = Math.atan2(y2 - y1, x2 - x1);
            const headLength = 10;
            ctx.strokeStyle = '#00bcd4'; // Match arrow color
            ctx.beginPath();
            ctx.moveTo(x2, y2);
            ctx.lineTo(
                x2 - headLength * Math.cos(angle - Math.PI / 6),
                y2 - headLength * Math.sin(angle - Math.PI / 6)
            );
            ctx.moveTo(x2, y2);
            ctx.lineTo(
                x2 - headLength * Math.cos(angle + Math.PI / 6),
                y2 - headLength * Math.sin(angle + Math.PI / 6)
            );
            ctx.stroke();
            
            // Calculate positions for labels
            const midX = (x1 + x2) / 2;
            const midY = (y1 + y2) / 2;
            
            // Position "from" direction closer to origin (25% along the line)
            const fromLabelX = x1 + (x2 - x1) * 0.25;
            const fromLabelY = y1 + (y2 - y1) * 0.25;
            
            // Position cost in the middle
            const costX = midX;
            const costY = midY;
            
            // Position "to" direction closer to destination (75% along the line)
            const toLabelX = x1 + (x2 - x1) * 0.75;
            const toLabelY = y1 + (y2 - y1) * 0.75;
            
            // Calculate perpendicular offset for text positioning
            const perpAngle = angle + Math.PI / 2;
            const textOffset = 8;
            
            ctx.fillStyle = '#8a8aaa';
            ctx.font = '10px sans-serif';
            ctx.textAlign = 'center';
            
            // Check if there's a reverse connection
            const reverseConn = connections.find(c => c.from === conn.to && c.to === conn.from);
            
            if (reverseConn) {
                // If bidirectional, offset labels to avoid overlap
                // "from" direction on one side
                ctx.fillText(
                    conn.direction, 
                    fromLabelX + Math.cos(perpAngle) * textOffset,
                    fromLabelY + Math.sin(perpAngle) * textOffset
                );
                
                // "to" direction (reverse) on the other side
                ctx.fillText(
                    reverseConn.direction,
                    toLabelX - Math.cos(perpAngle) * textOffset,
                    toLabelY - Math.sin(perpAngle) * textOffset
                );
            } else {
                // Single direction - center the label
                ctx.fillText(conn.direction, fromLabelX, fromLabelY - 5);
            }
            
            // Draw distance/cost in the middle
            const distance = Math.sqrt(Math.pow(toLoc.x - fromLoc.x, 2) + Math.pow(toLoc.y - fromLoc.y, 2));
            const cost = conn.stamina_cost || Math.ceil(distance * 2); // Use actual cost if available
            ctx.fillStyle = '#ffb74d';
            ctx.fillText(`⚡${cost}`, costX, costY + 3);
        }
    });
}

function drawLocations(centerX, centerY) {
    const dangerColors = ['#4caf50', '#8bc34a', '#ffa726', '#ff5722', '#d32f2f'];
    
    currentLocations.forEach(location => {
        const x = centerX + location.x * scale;
        const y = centerY - location.y * scale;
        
        // Draw location circle
        const color = dangerColors[location.danger_level] || '#9e9e9e';
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc(x, y, 15, 0, Math.PI * 2);
        ctx.fill();
        
        // Highlight selected
        if (location.id === selectedLocationId) {
            ctx.strokeStyle = '#ffa726';
            ctx.lineWidth = 3;
            ctx.stroke();
        }
        
        // Draw label
        ctx.fillStyle = '#e0e0e0';
        ctx.font = '12px sans-serif';
        ctx.textAlign = 'center';
        ctx.fillText(location.name, x, y + 30);
        
        // Draw live stats badges
        const playerCount = liveStats.players[location.id] || 0;
        const enemyCount = liveStats.enemies[location.id] || 0;
        
        let badgeY = y - 20;
        
        if (playerCount > 0) {
            drawBadge(x - 10, badgeY, `👥${playerCount}`, '#2196f3');
            badgeY -= 15;
        }
        
        if (enemyCount > 0) {
            drawBadge(x + 10, badgeY, `👹${enemyCount}`, '#f44336');
        }
    });
}

function drawBadge(x, y, text, color) {
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.arc(x, y, 12, 0, Math.PI * 2);
    ctx.fill();
    
    ctx.fillStyle = '#ffffff';
    ctx.font = 'bold 9px sans-serif';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(text, x, y);
    ctx.textBaseline = 'alphabetic';
}

// ==================== MOUSE INTERACTION ====================

function handleMouseDown(e) {
    const rect = canvas.getBoundingClientRect();
    const mouseX = e.clientX - rect.left;
    const mouseY = e.clientY - rect.top;
    
    clickStartTime = Date.now();
    clickStartPos = {x: mouseX, y: mouseY};
    dragStartX = mouseX - offsetX;
    dragStartY = mouseY - offsetY;
}

function handleMouseMove(e) {
    if (e.buttons === 1) { // Left mouse button
        const rect = canvas.getBoundingClientRect();
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;
        
        // Check if moved enough to be a drag
        const dx = mouseX - clickStartPos.x;
        const dy = mouseY - clickStartPos.y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        
        if (distance > 5) {
            isDragging = true;
            canvas.style.cursor = 'grabbing';
            offsetX = mouseX - dragStartX;
            offsetY = mouseY - dragStartY;
            drawMap();
        }
    }
}

function handleMouseUp(e) {
    const clickDuration = Date.now() - clickStartTime;
    
    if (!isDragging && clickDuration < 300) {
        // This was a click, not a drag
        handleCanvasClick(e);
    }
    
    isDragging = false;
    canvas.style.cursor = 'crosshair';
}

function handleWheel(e) {
    e.preventDefault();
    
    const rect = canvas.getBoundingClientRect();
    const mouseX = e.clientX - rect.left;
    const mouseY = e.clientY - rect.top;
    
    // Get world position before zoom
    const centerX = canvas.width / 2 + offsetX;
    const centerY = canvas.height / 2 + offsetY;
    const worldX = (mouseX - centerX) / scale;
    const worldY = -(mouseY - centerY) / scale;
    
    // Zoom
    const zoomFactor = e.deltaY < 0 ? 1.1 : 0.9;
    const newScale = Math.max(minScale, Math.min(maxScale, scale * zoomFactor));
    
    if (newScale !== scale) {
        // Adjust offset to keep mouse position stable
        const newCenterX = canvas.width / 2 + offsetX;
        const newCenterY = canvas.height / 2 + offsetY;
        const newScreenX = newCenterX + worldX * newScale;
        const newScreenY = newCenterY - worldY * newScale;
        
        offsetX += mouseX - newScreenX;
        offsetY += mouseY - newScreenY;
        
        scale = newScale;
        drawMap();
    }
}

function handleCanvasClick(e) {
    const rect = canvas.getBoundingClientRect();
    const clickX = e.clientX - rect.left;
    const clickY = e.clientY - rect.top;
    
    const centerX = canvas.width / 2 + offsetX;
    const centerY = canvas.height / 2 + offsetY;
    
    // Check if clicked on existing location
    for (const location of currentLocations) {
        const screenX = centerX + location.x * scale;
        const screenY = centerY - location.y * scale;
        
        const distance = Math.sqrt(Math.pow(clickX - screenX, 2) + Math.pow(clickY - screenY, 2));
        
        if (distance < 15) {
            selectLocation(location.id);
            return;
        }
    }
    
    // Clicked on empty space - create new location
    const worldX = ((clickX - centerX) / scale).toFixed(1);
    const worldY = (-(clickY - centerY) / scale).toFixed(1);
    
    if (confirm(`Create new location at (${worldX}, ${worldY})?`)) {
        createLocationAt(parseFloat(worldX), parseFloat(worldY));
    }
}

// ==================== ZOOM CONTROLS ====================

function zoomIn() {
    scale = Math.min(maxScale, scale * 1.2);
    drawMap();
}

function zoomOut() {
    scale = Math.max(minScale, scale / 1.2);
    drawMap();
}

function resetView() {
    scale = 50;
    offsetX = 0;
    offsetY = 0;
    drawMap();
}

// ==================== LOCATION MANAGEMENT ====================

function createLocationAt(x, y) {
    const newId = 'location_' + Date.now();
    
    const newLocation = {
        id: newId,
        name: 'New Location',
        description: 'Enter description...',
        image_path: '',
        x: x,
        y: y,
        danger_level: 0,
        encounter_rate: 0.0,
        wandering_chance: 0.0,
        spawn_npcs: []
    };
    
    currentLocations.push(newLocation);
    selectedLocationId = newId;
    renderLocationList();
    populateForm(newLocation);
    drawMap();
}

function createNewLocation() {
    createLocationAt(0, 0);
}

async function saveLocation() {
    const locationData = {
        id: document.getElementById('locationId').value,
        name: document.getElementById('locationName').value,
        description: document.getElementById('locationDescription').value,
        x: parseFloat(document.getElementById('locationX').value),
        y: parseFloat(document.getElementById('locationY').value),
        danger_level: parseInt(document.getElementById('dangerLevel').value),
        encounter_rate: parseFloat(document.getElementById('encounterRate').value),
        wandering_chance: parseFloat(document.getElementById('wanderingChance').value),
        image_path: document.getElementById('imagePath').value,
        spawn_npcs: getCurrentSpawns(),
        interactables: getInteractableInstances()
    };
    
    try {
        const response = await fetch('/api/editor/location', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(locationData)
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Location saved successfully!');
            await loadLocations();
            await loadConnections();
            drawMap();
        } else {
            alert('Failed to save: ' + data.error);
        }
    } catch (error) {
        alert('Failed to save location: ' + error.message);
    }
}

async function deleteCurrentLocation() {
    const locationId = document.getElementById('locationId').value;
    
    if (!confirm(`Delete location "${locationId}"? This will also remove all connections to/from this location.`)) {
        return;
    }
    
    try {
        const response = await fetch(`/api/editor/location/${locationId}`, {
            method: 'DELETE'
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Location deleted successfully!');
            selectedLocationId = null;
            document.getElementById('noSelectionMessage').classList.remove('hidden');
            document.getElementById('propertiesForm').classList.add('hidden');
            await loadLocations();
            await loadConnections();
            drawMap();
        } else {
            alert('Failed to delete: ' + data.error);
        }
    } catch (error) {
        alert('Failed to delete location: ' + error.message);
    }
}

// Wrapper functions for header buttons
function saveCurrentLocation() {
    if (!selectedLocationId) {
        alert('Please select a location first');
        return;
    }
    saveLocation();
}

// ==================== CONNECTION MANAGEMENT ====================

function showAddConnectionModal() {
    const modal = document.getElementById('addConnectionModal');
    const searchInput = document.getElementById('connectionSearch');
    
    // Clear search
    searchInput.value = '';
    
    // Populate the list
    filterConnectionList();
    
    modal.style.display = 'flex';
    searchInput.focus();
}

function filterConnectionList() {
    const list = document.getElementById('connectionTargetList');
    const searchTerm = document.getElementById('connectionSearch').value.toLowerCase();
    const currentId = document.getElementById('locationId').value;
    
    list.innerHTML = '';
    
    const filteredLocations = currentLocations.filter(location => {
        if (location.id === currentId) return false;
        if (!searchTerm) return true;
        return location.name.toLowerCase().includes(searchTerm) || 
               location.id.toLowerCase().includes(searchTerm);
    });
    
    if (filteredLocations.length === 0) {
        list.innerHTML = '<div style="padding: 20px; text-align: center; opacity: 0.5;">No locations found</div>';
        return;
    }
    
    filteredLocations.forEach(location => {
        const item = document.createElement('div');
        item.className = 'connection-target-item';
        item.innerHTML = `
            <div><strong>${location.name}</strong></div>
            <div style="font-size: 0.85em; opacity: 0.7;">
                📍 (${location.x}, ${location.y}) | Danger: ${location.danger_level}
            </div>
        `;
        
        item.onclick = () => promptAddConnection(currentId, location.id);
        list.appendChild(item);
    });
}

function closeAddConnectionModal() {
    document.getElementById('addConnectionModal').style.display = 'none';
}

function filterLocationList() {
    const searchTerm = document.getElementById('locationSearchInput').value.toLowerCase();
    const locationList = document.getElementById('locationList');
    const items = locationList.getElementsByClassName('location-item');
    
    Array.from(items).forEach(item => {
        const name = item.dataset.name ? item.dataset.name.toLowerCase() : '';
        const id = item.dataset.id ? item.dataset.id.toLowerCase() : '';
        
        if (!searchTerm || name.includes(searchTerm) || id.includes(searchTerm)) {
            item.style.display = '';
        } else {
            item.style.display = 'none';
        }
    });
}

function filterNPCList() {
    const searchTerm = document.getElementById('npcSearch').value.toLowerCase();
    const list = document.getElementById('npcSelectList');
    const items = list.getElementsByClassName('npc-item');
    
    Array.from(items).forEach(item => {
        const name = item.dataset.name ? item.dataset.name.toLowerCase() : '';
        const id = item.dataset.id ? item.dataset.id.toLowerCase() : '';
        
        if (!searchTerm || name.includes(searchTerm) || id.includes(searchTerm)) {
            item.style.display = '';
        } else {
            item.style.display = 'none';
        }
    });
}

async function promptAddConnection(fromId, toId) {
    const direction = prompt('Enter direction (north, south, east, west, northeast, etc.):');
    if (!direction) return;
    
    try {
        const response = await fetch('/api/editor/connection', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({from: fromId, to: toId, direction: direction.toLowerCase()})
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Connection added!');
            await loadConnections();
            await selectLocation(fromId); // Refresh form
            drawMap();
            closeAddConnectionModal();
        } else {
            alert('Failed to add connection: ' + data.error);
        }
    } catch (error) {
        alert('Failed to add connection: ' + error.message);
    }
}

async function deleteConnection(fromId, toId) {
    if (!confirm('Delete this connection?')) return;
    
    try {
        const response = await fetch('/api/editor/connection', {
            method: 'DELETE',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({from: fromId, to: toId})
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Connection deleted!');
            await loadConnections();
            await selectLocation(fromId); // Refresh form
            drawMap();
        } else {
            alert('Failed to delete connection: ' + data.error);
        }
    } catch (error) {
        alert('Failed to delete connection: ' + error.message);
    }
}

// ==================== SPAWN MANAGEMENT ====================

function getCurrentSpawns() {
    const spawns = [];
    const spawnItems = document.querySelectorAll('.spawn-item');
    
    spawnItems.forEach(item => {
        const nameDiv = item.querySelector('.spawn-item-name');
        const weightDiv = item.querySelector('.spawn-item-weight');
        
        if (nameDiv && weightDiv) {
            const text = nameDiv.textContent;
            const npcName = text.substring(text.indexOf(' ') + 1).trim();
            const weight = parseInt(weightDiv.textContent.replace('Weight: ', ''));
            
            const npc = availableNPCs.find(n => n.name === npcName);
            if (npc) {
                spawns.push({npc_id: npc.id, weight: weight});
            }
        }
    });
    
    return spawns;
}

function showAddSpawnModal() {
    const modal = document.getElementById('addSpawnModal');
    const list = document.getElementById('npcSelectList');
    
    list.innerHTML = '';
    
    // Clear search input
    document.getElementById('npcSearch').value = '';
    
    availableNPCs.forEach(npc => {
        const item = document.createElement('div');
        item.className = 'npc-item npc-select-item';
        item.dataset.name = npc.name;
        item.dataset.id = npc.id;
        item.innerHTML = `
            <div><strong>${npc.emoji} ${npc.name}</strong></div>
            <div style="font-size: 0.85em; opacity: 0.7;">
                HP: ${npc.hp_range[0]}-${npc.hp_range[1]} | 
                DMG: ${npc.damage_range[0]}-${npc.damage_range[1]} | 
                XP: ${npc.xp_reward}
            </div>
        `;
        
        item.onclick = () => addSpawn(npc);
        list.appendChild(item);
    });
    
    modal.style.display = 'flex';
    
    // Focus the search input
    setTimeout(() => document.getElementById('npcSearch').focus(), 100);
}

function closeAddSpawnModal() {
    document.getElementById('addSpawnModal').style.display = 'none';
}

function addSpawn(npc) {
    const weight = prompt(`Enter spawn weight for ${npc.name}:`, '50');
    if (weight && !isNaN(weight)) {
        const list = document.getElementById('spawnList');
        const item = document.createElement('div');
        item.className = 'spawn-item';
        item.innerHTML = `
            <div class="spawn-item-info">
                <div class="spawn-item-name">${npc.emoji} ${npc.name}</div>
                <div class="spawn-item-weight">Weight: ${weight}</div>
            </div>
            <button class="btn btn-remove" onclick="this.parentElement.remove()">Remove</button>
        `;
        list.appendChild(item);
    }
    closeAddSpawnModal();
}

function removeSpawn(index) {
    const spawnItems = document.querySelectorAll('.spawn-item');
    if (spawnItems[index]) {
        spawnItems[index].remove();
    }
}

// ==================== INTERACTABLE INSTANCES ====================

let currentEditingInteractableInstanceId = null;

async function showAddInteractableModal() {
    const modal = document.getElementById('addInteractableModal');
    const list = document.getElementById('interactableSelectList');
    
    list.innerHTML = '<div style="padding: 20px; text-align: center; opacity: 0.5;">Loading interactables...</div>';
    modal.style.display = 'flex';
    
    // Clear search input
    document.getElementById('interactableSearch').value = '';
    
    console.log('Current availableInteractables:', availableInteractables);
    
    // Ensure interactables are loaded
    if (!availableInteractables || availableInteractables.length === 0) {
        console.log('Loading interactables...');
        await loadAvailableInteractablesForLocations();
    }
    
    // Clear the loading message
    list.innerHTML = '';
    
    console.log('After loading, availableInteractables:', availableInteractables);
    
    // Check again after loading
    if (!availableInteractables || availableInteractables.length === 0) {
        console.log('No interactables found after loading');
        list.innerHTML = '<div style="padding: 20px; text-align: center; opacity: 0.5;">No interactables available. Create one in the Interactables tab first.</div>';
        return;
    }
    
    console.log(`Rendering ${availableInteractables.length} interactables`);
    
    availableInteractables.forEach(interactable => {
        const item = document.createElement('div');
        item.className = 'npc-item npc-select-item';
        item.dataset.name = interactable.name;
        item.dataset.id = interactable.id;
        const actionCount = Object.keys(interactable.actions || {}).length;
        item.innerHTML = `
            <div><strong>${interactable.name}</strong></div>
            <div style="font-size: 0.85em; opacity: 0.7;">
                ${interactable.description}<br>
                ${actionCount} action(s)
            </div>
        `;
        
        item.onclick = () => addInteractableToLocation(interactable);
        list.appendChild(item);
    });
    
    // Focus the search input
    setTimeout(() => document.getElementById('interactableSearch').focus(), 100);
}

function closeAddInteractableModal() {
    document.getElementById('addInteractableModal').style.display = 'none';
}

function filterInteractableSelectList() {
    const search = document.getElementById('interactableSearch').value.toLowerCase();
    const items = document.querySelectorAll('#interactableSelectList .npc-select-item');
    
    items.forEach(item => {
        const name = item.dataset.name.toLowerCase();
        if (name.includes(search)) {
            item.style.display = 'flex';
        } else {
            item.style.display = 'none';
        }
    });
}

function addInteractableToLocation(interactable) {
    // Generate a unique instance ID
    const instanceId = `${interactable.id}_${Date.now()}`;
    
    // Create instance with default outcomes
    const instance = {
        template_id: interactable.id,
        outcomes: {}
    };
    
    // Initialize default outcomes for each action
    // Actions is an object, not an array
    for (const [actionId, action] of Object.entries(interactable.actions || {})) {
        instance.outcomes[actionId] = {
            success_rate: 0.5,
            stamina_cost: action.stamina_cost || 0,
            text: {
                success: `You successfully ${action.label.toLowerCase()}.`,
                failure: `You failed to ${action.label.toLowerCase()}.`
            },
            rewards: {
                items: [],
                damage: 0
            }
        };
    }
    
    // Add to UI list
    const list = document.getElementById('interactablesList');
    const item = document.createElement('div');
    item.className = 'spawn-item';
    item.dataset.instanceId = instanceId;
    const actionCount = Object.keys(interactable.actions || {}).length;
    item.innerHTML = `
        <div class="spawn-item-info">
            <div class="spawn-item-name">${interactable.name}</div>
            <div class="spawn-item-weight">${actionCount} action(s)</div>
        </div>
        <div style="display: flex; gap: 5px;">
            <button class="btn btn-primary" onclick="editInteractableInstance('${instanceId}', '${interactable.id}')">Edit</button>
            <button class="btn btn-remove" onclick="removeInteractableInstance('${instanceId}')">Remove</button>
        </div>
    `;
    
    // Store instance data
    item.dataset.instanceData = JSON.stringify(instance);
    
    list.appendChild(item);
    closeAddInteractableModal();
}

function removeInteractableInstance(instanceId) {
    const items = document.querySelectorAll('.spawn-item');
    items.forEach(item => {
        if (item.dataset.instanceId === instanceId) {
            item.remove();
        }
    });
}

function editInteractableInstance(instanceId, templateId) {
    currentEditingInteractableInstanceId = instanceId;
    
    // Find the instance element
    const items = document.querySelectorAll('.spawn-item');
    let instanceElement = null;
    items.forEach(item => {
        if (item.dataset.instanceId === instanceId) {
            instanceElement = item;
        }
    });
    
    if (!instanceElement) return;
    
    const instanceData = JSON.parse(instanceElement.dataset.instanceData);
    const template = availableInteractables.find(i => i.id === templateId);
    
    if (!template) {
        alert('Template not found!');
        return;
    }
    
    // Build the editor UI
    const editor = document.getElementById('interactableInstanceEditor');
    editor.innerHTML = `
        <div style="background: rgba(255,255,255,0.05); padding: 15px; border-radius: 8px; margin-bottom: 20px;">
            <h4 style="margin: 0 0 5px 0;">${template.name}</h4>
            <p style="margin: 0; opacity: 0.7; font-size: 0.9em;">${template.description}</p>
        </div>
        
        <div style="display: flex; flex-direction: column; gap: 20px;">
            ${Object.entries(template.actions || {}).map(([actionId, action]) => {
                const outcome = instanceData.outcomes[actionId] || {};
                return `
                    <div style="background: rgba(255,255,255,0.03); padding: 15px; border-radius: 8px;">
                        <h4 style="margin: 0 0 15px 0;">Action: ${action.label}</h4>
                        
                        <div class="property-group">
                            <label>Success Rate (0.0-1.0)</label>
                            <input type="number" id="success_rate_${actionId}" 
                                   min="0" max="1" step="0.1" 
                                   value="${outcome.success_rate || 0.5}">
                        </div>
                        
                        <div class="property-group">
                            <label>Stamina Cost</label>
                            <input type="number" id="stamina_cost_${actionId}" 
                                   min="0" step="1" 
                                   value="${outcome.stamina_cost || action.stamina_cost || 0}">
                        </div>
                        
                        <div class="property-group">
                            <label>Success Text</label>
                            <textarea id="success_text_${actionId}" rows="2">${outcome.text?.success || ''}</textarea>
                        </div>
                        
                        <div class="property-group">
                            <label>Failure Text</label>
                            <textarea id="failure_text_${actionId}" rows="2">${outcome.text?.failure || ''}</textarea>
                        </div>
                        
                        <div class="property-group">
                            <label>Critical Success Text</label>
                            <textarea id="crit_success_text_${actionId}" rows="2">${outcome.text?.crit_success || ''}</textarea>
                        </div>
                        
                        <div class="property-group">
                            <label>Critical Failure Text</label>
                            <textarea id="crit_failure_text_${actionId}" rows="2">${outcome.text?.crit_failure || ''}</textarea>
                        </div>
                        
                        <div class="property-group">
                            <label>Critical Success Chance (0.0-1.0)</label>
                            <input type="number" id="crit_success_chance_${actionId}" 
                                   min="0" max="1" step="0.05" 
                                   value="${outcome.crit_success_chance || 0.1}">
                        </div>
                        
                        <div class="property-group">
                            <label>Critical Failure Chance (0.0-1.0)</label>
                            <input type="number" id="crit_failure_chance_${actionId}" 
                                   min="0" max="1" step="0.05" 
                                   value="${outcome.crit_failure_chance || 0.1}">
                        </div>
                        
                        <div class="property-group">
                            <label>Damage on Failure</label>
                            <input type="number" id="damage_${actionId}" 
                                   min="0" step="1" 
                                   value="${outcome.rewards?.damage || 0}">
                        </div>
                        
                        <div class="property-group">
                            <label>Damage on Critical Failure</label>
                            <input type="number" id="crit_damage_${actionId}" 
                                   min="0" step="1" 
                                   value="${outcome.rewards?.crit_damage || 0}">
                        </div>
                        
                        <div class="property-group" style="grid-column: 1 / -1;">
                            <label>Item Rewards</label>
                            <div style="display: flex; gap: 10px; margin-bottom: 5px; font-size: 0.9em; opacity: 0.7; padding: 0 5px;">
                                <div style="flex: 2;">Item (type to search)</div>
                                <div style="flex: 1;">Quantity</div>
                                <div style="flex: 1;">Chance (0-1)</div>
                                <div style="width: 40px;"></div>
                            </div>
                            <div id="item_rewards_${actionId}" style="margin-bottom: 10px;">
                                ${(outcome.rewards?.items || []).map((reward, idx) => {
                                    const selectedItem = availableItems.find(i => i.id === reward.item_id);
                                    const displayValue = selectedItem ? `${selectedItem.emoji || '📦'} ${selectedItem.name}` : '';
                                    return `
                                    <div class="reward-item" style="display: flex; gap: 10px; margin-bottom: 5px; align-items: center; position: relative;">
                                        <div style="flex: 2; position: relative;">
                                            <input type="text" class="reward-item-search" 
                                                   value="${displayValue}"
                                                   placeholder="Type to search items..."
                                                   oninput="filterItemDropdown(this)"
                                                   onfocus="showItemDropdown(this)"
                                                   style="width: 100%; padding: 8px; background: #1a1a3e; color: #e0e0e0; border: 1px solid #3a3a6a; border-radius: 4px;">
                                            <input type="hidden" class="reward-item-id" value="${reward.item_id || ''}">
                                            <div class="item-dropdown" style="display: none; position: absolute; top: 100%; left: 0; right: 0; max-height: 200px; overflow-y: auto; background: #1a1a3e; border: 1px solid #3a3a6a; border-radius: 4px; margin-top: 2px; z-index: 1000;"></div>
                                        </div>
                                        <input type="number" placeholder="1" value="${reward.quantity || 1}" 
                                               min="1" style="flex: 1;" class="reward-quantity">
                                        <input type="number" placeholder="1.0" value="${reward.chance || 1}" 
                                               min="0" max="1" step="0.1" style="flex: 1;" class="reward-chance">
                                        <button class="btn btn-remove" onclick="this.parentElement.remove()">×</button>
                                    </div>
                                `;
                                }).join('')}
                            </div>
                            <button class="btn btn-add" onclick="addRewardRow('${actionId}')">+ Add Item Reward</button>
                        </div>
                        
                        <div class="property-group" style="grid-column: 1 / -1;">
                            <label>Critical Success Item Rewards</label>
                            <div style="display: flex; gap: 10px; margin-bottom: 5px; font-size: 0.9em; opacity: 0.7; padding: 0 5px;">
                                <div style="flex: 2;">Item (type to search)</div>
                                <div style="flex: 1;">Quantity</div>
                                <div style="flex: 1;">Chance (0-1)</div>
                                <div style="width: 40px;"></div>
                            </div>
                            <div id="crit_item_rewards_${actionId}" style="margin-bottom: 10px;">
                                ${(outcome.rewards?.crit_items || []).map((reward, idx) => {
                                    const selectedItem = availableItems.find(i => i.id === reward.item_id);
                                    const displayValue = selectedItem ? `${selectedItem.emoji || '📦'} ${selectedItem.name}` : '';
                                    return `
                                    <div class="reward-item" style="display: flex; gap: 10px; margin-bottom: 5px; align-items: center; position: relative;">
                                        <div style="flex: 2; position: relative;">
                                            <input type="text" class="reward-item-search" 
                                                   value="${displayValue}"
                                                   placeholder="Type to search items..."
                                                   oninput="filterItemDropdown(this)"
                                                   onfocus="showItemDropdown(this)"
                                                   style="width: 100%; padding: 8px; background: #1a1a3e; color: #e0e0e0; border: 1px solid #3a3a6a; border-radius: 4px;">
                                            <input type="hidden" class="reward-item-id" value="${reward.item_id || ''}">
                                            <div class="item-dropdown" style="display: none; position: absolute; top: 100%; left: 0; right: 0; max-height: 200px; overflow-y: auto; background: #1a1a3e; border: 1px solid #3a3a6a; border-radius: 4px; margin-top: 2px; z-index: 1000;"></div>
                                        </div>
                                        <input type="number" placeholder="1" value="${reward.quantity || 1}" 
                                               min="1" style="flex: 1;" class="reward-quantity">
                                        <input type="number" placeholder="1.0" value="${reward.chance || 1}" 
                                               min="0" max="1" step="0.1" style="flex: 1;" class="reward-chance">
                                        <button class="btn btn-remove" onclick="this.parentElement.remove()">×</button>
                                    </div>
                                `;
                                }).join('')}
                            </div>
                            <button class="btn btn-add" onclick="addCritRewardRow('${actionId}')">+ Add Critical Success Reward</button>
                        </div>
                    </div>
                `;
            }).join('')}
        </div>
    `;
    
    document.getElementById('editInteractableInstanceModal').style.display = 'flex';
}

function closeEditInteractableInstanceModal() {
    document.getElementById('editInteractableInstanceModal').style.display = 'none';
    currentEditingInteractableInstanceId = null;
}

function addRewardRow(actionId) {
    const container = document.getElementById(`item_rewards_${actionId}`);
    const div = document.createElement('div');
    div.className = 'reward-item';
    div.style.display = 'flex';
    div.style.gap = '10px';
    div.style.marginBottom = '5px';
    div.style.alignItems = 'center';
    div.style.position = 'relative';
    
    div.innerHTML = `
        <div style="flex: 2; position: relative;">
            <input type="text" class="reward-item-search" 
                   placeholder="Type to search items..."
                   oninput="filterItemDropdown(this)"
                   onfocus="showItemDropdown(this)"
                   style="width: 100%; padding: 8px; background: #1a1a3e; color: #e0e0e0; border: 1px solid #3a3a6a; border-radius: 4px;">
            <input type="hidden" class="reward-item-id" value="">
            <div class="item-dropdown" style="display: none; position: absolute; top: 100%; left: 0; right: 0; max-height: 200px; overflow-y: auto; background: #1a1a3e; border: 1px solid #3a3a6a; border-radius: 4px; margin-top: 2px; z-index: 1000;"></div>
        </div>
        <input type="number" placeholder="1" value="1" min="1" style="flex: 1;" class="reward-quantity">
        <input type="number" placeholder="1.0" value="1" min="0" max="1" step="0.1" style="flex: 1;" class="reward-chance">
        <button class="btn btn-remove" onclick="this.parentElement.remove()">×</button>
    `;
    container.appendChild(div);
}

function addCritRewardRow(actionId) {
    const container = document.getElementById(`crit_item_rewards_${actionId}`);
    const div = document.createElement('div');
    div.className = 'reward-item';
    div.style.display = 'flex';
    div.style.gap = '10px';
    div.style.marginBottom = '5px';
    div.style.alignItems = 'center';
    div.style.position = 'relative';
    
    div.innerHTML = `
        <div style="flex: 2; position: relative;">
            <input type="text" class="reward-item-search" 
                   placeholder="Type to search items..."
                   oninput="filterItemDropdown(this)"
                   onfocus="showItemDropdown(this)"
                   style="width: 100%; padding: 8px; background: #1a1a3e; color: #e0e0e0; border: 1px solid #3a3a6a; border-radius: 4px;">
            <input type="hidden" class="reward-item-id" value="">
            <div class="item-dropdown" style="display: none; position: absolute; top: 100%; left: 0; right: 0; max-height: 200px; overflow-y: auto; background: #1a1a3e; border: 1px solid #3a3a6a; border-radius: 4px; margin-top: 2px; z-index: 1000;"></div>
        </div>
        <input type="number" placeholder="1" value="1" min="1" style="flex: 1;" class="reward-quantity">
        <input type="number" placeholder="1.0" value="1" min="0" max="1" step="0.1" style="flex: 1;" class="reward-chance">
        <button class="btn btn-remove" onclick="this.parentElement.remove()">×</button>
    `;
    container.appendChild(div);
}

// Autocomplete functions for item selection
function showItemDropdown(input) {
    filterItemDropdown(input);
}

function filterItemDropdown(input) {
    const searchText = input.value.toLowerCase();
    const dropdown = input.parentElement.querySelector('.item-dropdown');
    const hiddenInput = input.parentElement.querySelector('.reward-item-id');
    
    if (!dropdown) return;
    
    // Filter items
    const filteredItems = availableItems.filter(item => {
        const itemText = `${item.emoji || ''} ${item.name || ''} ${item.id}`.toLowerCase();
        return itemText.includes(searchText);
    });
    
    // Build dropdown HTML
    dropdown.innerHTML = '';
    dropdown.style.display = 'block';
    
    if (filteredItems.length === 0) {
        dropdown.innerHTML = '<div style="padding: 8px; opacity: 0.5;">No items found</div>';
        return;
    }
    
    // Create elements dynamically with proper event listeners
    filteredItems.forEach(item => {
        const optionDiv = document.createElement('div');
        optionDiv.className = 'dropdown-item';
        optionDiv.style.padding = '8px';
        optionDiv.style.cursor = 'pointer';
        optionDiv.style.borderBottom = '1px solid #2a2a4a';
        
        optionDiv.innerHTML = `
            ${item.emoji || '📦'} ${item.name || item.id}
            <span style="opacity: 0.5; font-size: 0.85em; margin-left: 5px;">${item.id}</span>
        `;
        
        // Add hover effects
        optionDiv.addEventListener('mouseover', function() {
            this.style.background = '#2a2a4a';
        });
        optionDiv.addEventListener('mouseout', function() {
            this.style.background = 'transparent';
        });
        
        // Add click handler
        optionDiv.addEventListener('click', function(e) {
            e.stopPropagation();
            // Set the visible input to show emoji + name
            input.value = `${item.emoji || '📦'} ${item.name || item.id}`;
            // Set the hidden input to store the item_id
            hiddenInput.value = item.id;
            dropdown.style.display = 'none';
        });
        
        dropdown.appendChild(optionDiv);
    });
}

function selectItem(element) {
    const itemId = element.dataset.id;
    const itemName = element.dataset.name;
    const container = element.closest('.reward-item');
    const searchInput = container.querySelector('.reward-item-search');
    const hiddenInput = container.querySelector('.reward-item-id');
    const dropdown = container.querySelector('.item-dropdown');
    
    searchInput.value = itemName;
    hiddenInput.value = itemId;
    dropdown.style.display = 'none';
}

// Close dropdowns when clicking outside
document.addEventListener('click', (e) => {
    if (!e.target.closest('.reward-item')) {
        document.querySelectorAll('.item-dropdown').forEach(dropdown => {
            dropdown.style.display = 'none';
        });
    }
});

function saveInteractableInstance() {
    if (!currentEditingInteractableInstanceId) return;
    
    // Find the instance element
    const items = document.querySelectorAll('.spawn-item');
    let instanceElement = null;
    items.forEach(item => {
        if (item.dataset.instanceId === currentEditingInteractableInstanceId) {
            instanceElement = item;
        }
    });
    
    if (!instanceElement) return;
    
    const instanceData = JSON.parse(instanceElement.dataset.instanceData);
    const template = availableInteractables.find(i => i.id === instanceData.template_id);
    
    if (!template) return;
    
    // Collect all outcomes
    for (const [actionId, action] of Object.entries(template.actions || {})) {
        const successRate = parseFloat(document.getElementById(`success_rate_${actionId}`).value);
        const staminaCost = parseInt(document.getElementById(`stamina_cost_${actionId}`).value);
        const successText = document.getElementById(`success_text_${actionId}`).value;
        const failureText = document.getElementById(`failure_text_${actionId}`).value;
        const critSuccessText = document.getElementById(`crit_success_text_${actionId}`).value;
        const critFailureText = document.getElementById(`crit_failure_text_${actionId}`).value;
        const critSuccessChance = parseFloat(document.getElementById(`crit_success_chance_${actionId}`).value);
        const critFailureChance = parseFloat(document.getElementById(`crit_failure_chance_${actionId}`).value);
        const damage = parseInt(document.getElementById(`damage_${actionId}`).value);
        const critDamage = parseInt(document.getElementById(`crit_damage_${actionId}`).value);
        
        // Collect item rewards
        const rewardContainer = document.getElementById(`item_rewards_${actionId}`);
        const rewardItems = rewardContainer.querySelectorAll('.reward-item');
        const items = [];
        
        rewardItems.forEach(rewardItem => {
            const itemId = rewardItem.querySelector('.reward-item-id').value;
            const quantity = parseInt(rewardItem.querySelector('.reward-quantity').value);
            const chance = parseFloat(rewardItem.querySelector('.reward-chance').value);
            
            if (itemId) {
                items.push({
                    item_id: itemId,
                    quantity: quantity || 1,
                    chance: chance || 1
                });
            }
        });
        
        // Collect critical success item rewards
        const critRewardContainer = document.getElementById(`crit_item_rewards_${actionId}`);
        const critRewardItems = critRewardContainer.querySelectorAll('.reward-item');
        const critItems = [];
        
        critRewardItems.forEach(rewardItem => {
            const itemId = rewardItem.querySelector('.reward-item-id').value;
            const quantity = parseInt(rewardItem.querySelector('.reward-quantity').value);
            const chance = parseFloat(rewardItem.querySelector('.reward-chance').value);
            
            if (itemId) {
                critItems.push({
                    item_id: itemId,
                    quantity: quantity || 1,
                    chance: chance || 1
                });
            }
        });
        
        instanceData.outcomes[actionId] = {
            success_rate: successRate,
            stamina_cost: staminaCost,
            crit_success_chance: critSuccessChance,
            crit_failure_chance: critFailureChance,
            text: {
                success: successText,
                failure: failureText,
                crit_success: critSuccessText,
                crit_failure: critFailureText
            },
            rewards: {
                items: items,
                damage: damage,
                crit_items: critItems,
                crit_damage: critDamage
            }
        };
    }
    
    // Update the stored data
    instanceElement.dataset.instanceData = JSON.stringify(instanceData);
    
    closeEditInteractableInstanceModal();
    showSuccess('Interactable instance updated!');
}

function getInteractableInstances() {
    const instances = {};
    const items = document.querySelectorAll('#interactablesList .spawn-item');
    
    items.forEach(item => {
        const instanceId = item.dataset.instanceId;
        const instanceData = JSON.parse(item.dataset.instanceData);
        instances[instanceId] = instanceData;
    });
    
    return instances;
}

function renderInteractablesList(interactables) {
    console.log('renderInteractablesList called with:', interactables);
    console.log('availableInteractables:', availableInteractables);
    
    const list = document.getElementById('interactablesList');
    if (!list) {
        console.error('interactablesList element not found!');
        return;
    }
    
    list.innerHTML = '';
    
    if (!interactables || Object.keys(interactables).length === 0) {
        console.log('No interactables to render');
        return;
    }
    
    console.log('Rendering', Object.keys(interactables).length, 'interactables');
    
    Object.entries(interactables).forEach(([instanceId, instance]) => {
        // Support both old format (template_id) and new format (id)
        const templateId = instance.template_id || instance.id;
        let displayName = instance.name || 'Unknown';
        let actionCount = 0;
        
        console.log(`Processing instance ${instanceId}, template_id: ${templateId}`);
        
        // Try to find template in available interactables
        const template = availableInteractables.find(i => i.id === templateId);
        if (template) {
            displayName = template.name;
            actionCount = Object.keys(template.actions || {}).length;
            console.log(`Found template: ${displayName} with ${actionCount} actions`);
        } else {
            console.log(`Template ${templateId} not found in availableInteractables`);
            // For new format instances that have full data
            if (instance.name) {
                displayName = instance.name;
            }
            if (instance.actions) {
                actionCount = Object.keys(instance.actions).length;
            } else if (instance.outcomes) {
                actionCount = Object.keys(instance.outcomes).length;
            }
        }
        
        const item = document.createElement('div');
        item.className = 'spawn-item';
        item.dataset.instanceId = instanceId;
        item.dataset.instanceData = JSON.stringify(instance);
        item.innerHTML = `
            <div class="spawn-item-info">
                <div class="spawn-item-name">${displayName}</div>
                <div class="spawn-item-weight">${actionCount} action(s)</div>
            </div>
            <div style="display: flex; gap: 5px;">
                <button class="btn btn-primary" onclick="editInteractableInstance('${instanceId}', '${templateId}')">Edit</button>
                <button class="btn btn-remove" onclick="removeInteractableInstance('${instanceId}')">Remove</button>
            </div>
        `;
        
        list.appendChild(item);
        console.log(`Appended item for ${instanceId}`);
    });
    
    console.log('Finished rendering interactables');
}

// ==================== IMAGE UPLOAD ====================

async function uploadImage() {
    const fileInput = document.getElementById('imageUpload');
    const file = fileInput.files[0];
    
    if (!file) return;
    
    const formData = new FormData();
    formData.append('image', file);
    
    try {
        const response = await fetch('/api/editor/upload-image', {
            method: 'POST',
            body: formData
        });
        
        const data = await response.json();
        
        if (data.success) {
            document.getElementById('imagePath').value = data.image_path;
            updateImagePreview(data.image_path);
            showSuccess(data.message);
        } else {
            alert('Upload failed: ' + data.error);
        }
    } catch (error) {
        alert('Upload failed: ' + error.message);
    }
}

async function uploadNPCImage() {
    const fileInput = document.getElementById('npcImageUpload');
    const file = fileInput.files[0];
    
    if (!file) return;
    
    const formData = new FormData();
    formData.append('image', file);
    
    try {
        const response = await fetch('/api/editor/upload-image', {
            method: 'POST',
            body: formData
        });
        
        const data = await response.json();
        
        if (data.success) {
            document.getElementById('npcImageUrl').value = data.image_path;
            updateNPCImagePreview(data.image_path);
            showSuccess(data.message);
        } else {
            alert('Upload failed: ' + data.error);
        }
    } catch (error) {
        alert('Upload failed: ' + error.message);
    }
}

function updateNPCImagePreview(imagePath) {
    const preview = document.getElementById('npcImagePreview');
    if (imagePath && imagePath.trim() !== '') {
        preview.innerHTML = `<img src="${imagePath}" alt="NPC image" onerror="this.parentElement.innerHTML='<span>Image not found</span>'">`;
    } else {
        preview.innerHTML = '<span>No image</span>';
    }
}

async function uploadInteractableImage() {
    const fileInput = document.getElementById('interactableImageUpload');
    const file = fileInput.files[0];
    
    if (!file) return;
    
    const formData = new FormData();
    formData.append('image', file);
    
    try {
        const response = await fetch('/api/editor/upload-image', {
            method: 'POST',
            body: formData
        });
        
        const data = await response.json();
        
        if (data.success) {
            document.getElementById('interactableImagePath').value = data.image_path;
            updateInteractableImagePreview(data.image_path);
            showSuccess(data.message);
        } else {
            alert('Upload failed: ' + data.error);
        }
    } catch (error) {
        alert('Upload failed: ' + error.message);
    }
}

// ==================== PYTHON EXPORT ====================

async function exportToPython() {
    try {
        const response = await fetch('/api/editor/export-python');
        const data = await response.json();
        
        if (data.success) {
            // Create a downloadable file
            const blob = new Blob([data.python_code], {type: 'text/plain'});
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'world_loader_updates.py';
            a.click();
            URL.revokeObjectURL(url);
            
            showSuccess('Python code exported! Review before applying to world_loader.py');
        } else {
            alert('Export failed: ' + data.error);
        }
    } catch (error) {
        alert('Export failed: ' + error.message);
    }
}

// ==================== UTILITY ====================

async function logout() {
    try {
        await fetch('/api/logout', {method: 'POST'});
        if (liveStatsInterval) {
            clearInterval(liveStatsInterval);
        }
        window.location.reload();
    } catch (error) {
        console.error('Logout failed:', error);
    }
}

async function restartBot() {
    if (!confirm('Are you sure you want to restart the bot? This will temporarily disconnect active users.')) {
        return;
    }
    
    try {
        const response = await fetch('/api/editor/restart-bot', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            }
        });
        
        const data = await response.json();
        
        if (response.ok) {
            showSuccess('✅ Bot restarted successfully! Changes will be loaded.');
        } else {
            showError(`Failed to restart bot: ${data.error || 'Unknown error'}`);
        }
    } catch (error) {
        console.error('Restart failed:', error);
        showError('Failed to restart bot. Check console for details.');
    }
}

async function refreshBotLogs() {
    try {
        const lineCount = document.getElementById('logsLineCount').value || 100;
        const logsViewer = document.getElementById('logsViewer');
        
        logsViewer.innerHTML = '<div style="opacity: 0.5; text-align: center; padding: 20px;">Loading logs...</div>';
        
        const response = await fetch(`/api/editor/bot-logs?lines=${lineCount}`);
        const data = await response.json();
        
        if (response.ok && data.success) {
            displayLogs(data.logs);
        } else {
            logsViewer.innerHTML = `<div class="log-error">Failed to load logs: ${data.error || 'Unknown error'}</div>`;
        }
    } catch (error) {
        console.error('Failed to fetch logs:', error);
        document.getElementById('logsViewer').innerHTML = '<div class="log-error">Failed to fetch logs. Check console for details.</div>';
    }
}

function displayLogs(logsText) {
    const logsViewer = document.getElementById('logsViewer');
    
    if (!logsText || logsText.trim() === '') {
        logsViewer.innerHTML = '<div style="opacity: 0.5; text-align: center; padding: 20px;">No logs available</div>';
        return;
    }
    
    const lines = logsText.split('\n');
    let html = '';
    
    lines.forEach(line => {
        if (!line.trim()) return;
        
        let className = 'log-line';
        
        // Color code based on log level
        if (line.includes('ERROR') || line.includes('Error') || line.includes('error')) {
            className += ' log-error';
        } else if (line.includes('WARNING') || line.includes('Warning') || line.includes('warning')) {
            className += ' log-warning';
        } else if (line.includes('INFO') || line.includes('Info')) {
            className += ' log-info';
        } else if (line.includes('✅') || line.includes('SUCCESS') || line.includes('Success')) {
            className += ' log-success';
        }
        
        // Escape HTML to prevent XSS
        const escapedLine = line
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
        
        html += `<div class="${className}">${escapedLine}</div>`;
    });
    
    logsViewer.innerHTML = html;
    
    // Auto-scroll to bottom
    logsViewer.scrollTop = logsViewer.scrollHeight;
}

function clearLogsDisplay() {
    document.getElementById('logsViewer').innerHTML = '<div style="opacity: 0.5; text-align: center; padding: 20px;">Logs cleared. Click "Refresh" to reload.</div>';
}

// ==================== TAB SWITCHING ====================

function switchTab(tabName) {
    currentTab = tabName;
    
    // Update tab buttons
    document.querySelectorAll('.tab-button').forEach(btn => {
        if (btn.textContent.toLowerCase().includes(tabName)) {
            btn.classList.add('active');
        } else {
            btn.classList.remove('active');
        }
    });
    
    // Update tab content - ensure all are hidden first
    document.querySelectorAll('.tab-content').forEach(content => {
        content.classList.remove('active');
        content.style.display = 'none';
    });
    
    // Show only the selected tab
    const activeTab = document.getElementById(`tab-${tabName}`);
    if (activeTab) {
        activeTab.classList.add('active');
        activeTab.style.display = (tabName === 'locations') ? 'grid' : 'flex';
    }
    
    // Load data for the tab
    if (tabName === 'npcs') {
        loadNPCManagement();
    } else if (tabName === 'items') {
        loadItemManagement();
    } else if (tabName === 'interactables') {
        loadInteractableManagement();
    } else if (tabName === 'logs') {
        // Auto-load logs when switching to logs tab
        refreshBotLogs();
    } else if (tabName === 'locations') {
        // Load interactables for the locations tab (needed for adding instances)
        loadAvailableInteractablesForLocations();
        // Force canvas resize when switching to locations tab
        setTimeout(() => {
            resizeCanvas();
        }, 10);
    }
}

async function loadAvailableInteractablesForLocations() {
    try {
        const response = await fetch('/api/editor/interactables');
        const data = await response.json();
        
        console.log('Interactables API response:', data);
        
        if (data.interactables) {
            // Check if it's an array or object
            if (Array.isArray(data.interactables)) {
                availableInteractables = data.interactables;
            } else {
                // If it's an object, convert to array
                availableInteractables = Object.entries(data.interactables).map(([id, interactable]) => ({
                    id,
                    ...interactable
                }));
            }
            console.log('Loaded interactables:', availableInteractables.length);
        } else {
            console.error('No interactables in response');
            availableInteractables = [];
        }
    } catch (error) {
        console.error('Failed to load interactables:', error);
        availableInteractables = [];
    }
}

async function loadAvailableItemsForLocations() {
    try {
        const response = await fetch('/api/editor/items');
        const data = await response.json();
        availableItems = data.items || [];
    } catch (error) {
        console.error('Failed to load items:', error);
    }
}

function saveCurrentItem() {
    if (currentTab === 'locations') {
        saveCurrentLocation();
    } else if (currentTab === 'npcs') {
        saveCurrentNPC();
    } else if (currentTab === 'items') {
        saveCurrentItem_();
    } else if (currentTab === 'interactables') {
        saveCurrentInteractable();
    }
}

// ==================== NPC MANAGEMENT ====================

async function loadNPCManagement() {
    try {
        const response = await fetch('/api/editor/npcs', {
            credentials: 'same-origin'
        });
        const data = await response.json();
        availableNPCs = data.npcs || [];
        renderNPCManagementList();
    } catch (error) {
        console.error('Failed to load NPCs:', error);
    }
}

function renderNPCManagementList() {
    const list = document.getElementById('npcManagementList');
    list.innerHTML = '';
    
    availableNPCs.forEach(npc => {
        const item = document.createElement('div');
        item.className = 'management-item';
        item.dataset.name = npc.name;
        item.dataset.id = npc.id;
        if (npc.id === selectedNPCId) {
            item.classList.add('active');
        }
        
        item.innerHTML = `
            <div><strong>${npc.emoji} ${npc.name}</strong></div>
            <div style="font-size: 0.85em; opacity: 0.7; margin-top: 5px;">
                HP: ${npc.hp_min}-${npc.hp_max} | DMG: ${npc.damage_min}-${npc.damage_max}
            </div>
        `;
        
        item.onclick = () => selectNPC(npc.id);
        list.appendChild(item);
    });
}

function filterNPCManagementList() {
    const searchTerm = document.getElementById('npcManagementSearch').value.toLowerCase();
    const items = document.querySelectorAll('#npcManagementList .management-item');
    
    items.forEach(item => {
        const name = item.dataset.name?.toLowerCase() || '';
        const id = item.dataset.id?.toLowerCase() || '';
        item.style.display = (!searchTerm || name.includes(searchTerm) || id.includes(searchTerm)) ? '' : 'none';
    });
}

function selectNPC(npcId) {
    selectedNPCId = npcId;
    renderNPCManagementList();
    
    const npc = availableNPCs.find(n => n.id === npcId);
    if (!npc) return;
    
    const editor = document.getElementById('npcEditor');
    editor.innerHTML = `
        <h2>Edit NPC: ${npc.name}</h2>
        
        <div class="form-grid">
            <div class="property-group">
                <label>ID</label>
                <input type="text" id="npcId" value="${npc.id}" readonly style="opacity: 0.6;">
            </div>
            <div class="property-group">
                <label>Name</label>
                <input type="text" id="npcName" value="${npc.name}">
            </div>
            <div class="property-group">
                <label>Emoji</label>
                <input type="text" id="npcEmoji" value="${npc.emoji}" maxlength="2">
            </div>
        </div>
        
        <div class="form-grid">
            <div class="property-group">
                <label>HP Min</label>
                <input type="number" id="npcHpMin" value="${npc.hp_min}" min="1">
            </div>
            <div class="property-group">
                <label>HP Max</label>
                <input type="number" id="npcHpMax" value="${npc.hp_max}" min="1">
            </div>
        </div>
        
        <div class="form-grid">
            <div class="property-group">
                <label>Damage Min</label>
                <input type="number" id="npcDamageMin" value="${npc.damage_min}" min="0">
            </div>
            <div class="property-group">
                <label>Damage Max</label>
                <input type="number" id="npcDamageMax" value="${npc.damage_max}" min="0">
            </div>
        </div>
        
        <div class="form-grid">
            <div class="property-group">
                <label>XP Reward</label>
                <input type="number" id="npcXp" value="${npc.xp_reward}" min="0">
            </div>
            <div class="property-group">
                <label>Defense</label>
                <input type="number" id="npcDefense" value="${npc.defense || 0}" min="0">
            </div>
        </div>
        
        <div class="property-group">
            <label>Description</label>
            <textarea id="npcDescription" rows="3" style="width: 100%;">${npc.description || ''}</textarea>
        </div>
        
        <div class="property-group">
            <label>NPC Image</label>
            <input type="text" id="npcImageUrl" value="${npc.image_url || ''}" placeholder="images/npcs/npc_name.png" oninput="updateNPCImagePreview(this.value)">
            <div class="file-input-wrapper">
                <input type="file" id="npcImageUpload" accept="image/*" onchange="uploadNPCImage()">
                <label for="npcImageUpload" class="file-input-label">📤 Upload New Image</label>
            </div>
            <div class="image-preview" id="npcImagePreview">
                ${npc.image_url ? `<img src="${npc.image_url}" alt="NPC image" onerror="this.parentElement.innerHTML='<span>Image not found</span>'">` : '<span>No image</span>'}
            </div>
        </div>
        
        <h3 style="color: #ffa726; margin: 30px 0 15px;">Loot Table</h3>
        <div id="npcLootTable"></div>
        <button class="btn btn-add" onclick="addNPCLoot()">+ Add Loot Item</button>
        
        <h3 style="color: #ffa726; margin: 30px 0 15px;">Corpse Loot</h3>
        <div id="npcCorpseLoot"></div>
        <button class="btn btn-add" onclick="addNPCCorpseLoot()">+ Add Corpse Loot</button>
        
        <div style="margin-top: 30px; padding-top: 20px; border-top: 2px solid #3a3a6a; display: flex; gap: 10px;">
            <button class="btn btn-danger" style="flex: 1;" onclick="deleteCurrentNPC()">🗑️ Delete NPC</button>
        </div>
    `;
    
    renderNPCLootTable(npc.loot_table || []);
    renderNPCCorpseLoot(npc.corpse_loot || []);
}

function renderNPCLootTable(lootTable) {
    const container = document.getElementById('npcLootTable');
    container.innerHTML = '';
    
    lootTable.forEach((loot, index) => {
        // Handle both old and new formats for quantities
        let quantityMin = loot.quantity_min || 1;
        let quantityMax = loot.quantity_max || 1;
        
        // Parse quantity_range if it exists (old format)
        if (Array.isArray(loot.quantity_range)) {
            quantityMin = loot.quantity_range[0] || 1;
            quantityMax = loot.quantity_range[1] || 1;
        } else if (typeof loot.quantity_range === 'string') {
            try {
                const parsed = JSON.parse(loot.quantity_range);
                quantityMin = parsed[0] || 1;
                quantityMax = parsed[1] || 1;
            } catch (e) {
                quantityMin = 1;
                quantityMax = 1;
            }
        }
        
        const item = document.createElement('div');
        item.className = 'array-item';
        item.innerHTML = `
            <button class="array-item-remove" onclick="removeNPCLoot(${index})">×</button>
            <div class="form-grid">
                <div class="property-group">
                    <label>Item</label>
                    <div style="position: relative;">
                        <input type="text" 
                               id="lootItem${index}" 
                               value="${loot.item_id}" 
                               placeholder="Type to search items..."
                               oninput="filterNPCLootItemDropdown(${index})"
                               onfocus="showNPCLootItemDropdown(${index})"
                               autocomplete="off">
                        <div id="lootItemDropdown${index}" class="item-dropdown" style="display: none; position: absolute; top: 100%; left: 0; right: 0; max-height: 200px; overflow-y: auto; background: #1a1a3e; border: 1px solid #3a3a6a; border-radius: 4px; margin-top: 2px; z-index: 1000;"></div>
                    </div>
                </div>
                <div class="property-group">
                    <label>Quantity Min</label>
                    <input type="number" id="lootQuantityMin${index}" value="${quantityMin}" min="1">
                </div>
                <div class="property-group">
                    <label>Quantity Max</label>
                    <input type="number" id="lootQuantityMax${index}" value="${quantityMax}" min="1">
                </div>
                <div class="property-group">
                    <label>Drop Chance (0-1)</label>
                    <input type="number" id="lootChance${index}" value="${loot.drop_chance || 0.5}" step="0.01" min="0" max="1">
                </div>
            </div>
        `;
        container.appendChild(item);
    });
}

function renderNPCCorpseLoot(corpseLoot) {
    const container = document.getElementById('npcCorpseLoot');
    container.innerHTML = '';
    
    corpseLoot.forEach((loot, index) => {
        // Handle both old and new formats for quantities
        let quantityMin = loot.quantity_min || 1;
        let quantityMax = loot.quantity_max || 1;
        
        const item = document.createElement('div');
        item.className = 'array-item';
        item.innerHTML = `
            <button class="array-item-remove" onclick="removeNPCCorpseLoot(${index})">×</button>
            <div class="form-grid">
                <div class="property-group">
                    <label>Item</label>
                    <div style="position: relative;">
                        <input type="text" 
                               id="corpseItem${index}" 
                               value="${loot.item_id}" 
                               placeholder="Type to search items..."
                               oninput="filterNPCCorpseItemDropdown(${index})"
                               onfocus="showNPCCorpseItemDropdown(${index})"
                               autocomplete="off">
                        <div id="corpseItemDropdown${index}" class="item-dropdown" style="display: none; position: absolute; top: 100%; left: 0; right: 0; max-height: 200px; overflow-y: auto; background: #1a1a3e; border: 1px solid #3a3a6a; border-radius: 4px; margin-top: 2px; z-index: 1000;"></div>
                    </div>
                </div>
                <div class="property-group">
                    <label>Quantity Min</label>
                    <input type="number" id="corpseQuantityMin${index}" value="${quantityMin}" min="1">
                </div>
                <div class="property-group">
                    <label>Quantity Max</label>
                    <input type="number" id="corpseQuantityMax${index}" value="${quantityMax}" min="1">
                </div>
                <div class="property-group">
                    <label>Required Tool (optional)</label>
                    <input type="text" id="corpseRequiredTool${index}" value="${loot.required_tool || ''}" placeholder="e.g., knife">
                </div>
            </div>
        `;
        container.appendChild(item);
    });
}

function createNewNPC() {
    const npcId = prompt('Enter NPC ID (e.g., zombie, raider):');
    if (!npcId) return;
    
    const newNPC = {
        id: npcId,
        name: 'New NPC',
        emoji: '👹',
        hp_min: 10,
        hp_max: 20,
        damage_min: 1,
        damage_max: 5,
        xp_reward: 10,
        defense: 0,
        description: '',
        image_url: '',
        loot_table: [],
        corpse_loot: []
    };
    
    availableNPCs.push(newNPC);
    renderNPCManagementList();
    selectNPC(npcId);
}

async function saveCurrentNPC() {
    if (!selectedNPCId) {
        alert('No NPC selected');
        return;
    }
    
    const npcData = {
        id: document.getElementById('npcId').value,
        name: document.getElementById('npcName').value,
        emoji: document.getElementById('npcEmoji').value,
        hp_min: parseInt(document.getElementById('npcHpMin').value),
        hp_max: parseInt(document.getElementById('npcHpMax').value),
        damage_min: parseInt(document.getElementById('npcDamageMin').value),
        damage_max: parseInt(document.getElementById('npcDamageMax').value),
        xp_reward: parseInt(document.getElementById('npcXp').value),
        defense: parseInt(document.getElementById('npcDefense').value),
        description: document.getElementById('npcDescription').value,
        image_url: document.getElementById('npcImageUrl').value,
        loot_table: getNPCLootTable(),
        corpse_loot: getNPCCorpseLoot()
    };
    
    try {
        const response = await fetch('/api/editor/npc', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            credentials: 'same-origin',
            body: JSON.stringify(npcData)
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('NPC saved successfully!');
            await loadNPCManagement();
        } else {
            alert('Failed to save: ' + data.error);
        }
    } catch (error) {
        alert('Failed to save NPC: ' + error.message);
    }
}

function getNPCLootTable() {
    const container = document.getElementById('npcLootTable');
    const items = container.querySelectorAll('.array-item');
    const lootTable = [];
    
    items.forEach((item, index) => {
        const itemId = document.getElementById(`lootItem${index}`).value;
        const quantityMin = parseInt(document.getElementById(`lootQuantityMin${index}`).value);
        const quantityMax = parseInt(document.getElementById(`lootQuantityMax${index}`).value);
        const chance = parseFloat(document.getElementById(`lootChance${index}`).value);
        
        if (itemId) {
            lootTable.push({
                item_id: itemId,
                quantity_min: quantityMin,
                quantity_max: quantityMax,
                drop_chance: chance
            });
        }
    });
    
    return lootTable;
}

function getNPCCorpseLoot() {
    const container = document.getElementById('npcCorpseLoot');
    const items = container.querySelectorAll('.array-item');
    const corpseLoot = [];
    
    items.forEach((item, index) => {
        const itemId = document.getElementById(`corpseItem${index}`).value;
        const quantityMin = parseInt(document.getElementById(`corpseQuantityMin${index}`).value);
        const quantityMax = parseInt(document.getElementById(`corpseQuantityMax${index}`).value);
        const requiredTool = document.getElementById(`corpseRequiredTool${index}`).value || null;
        
        if (itemId) {
            corpseLoot.push({
                item_id: itemId,
                quantity_min: quantityMin,
                quantity_max: quantityMax,
                required_tool: requiredTool
            });
        }
    });
    
    return corpseLoot;
}

// Item dropdown functions for NPC loot tables
function showNPCLootItemDropdown(index) {
    filterNPCLootItemDropdown(index);
}

function filterNPCLootItemDropdown(index) {
    const input = document.getElementById(`lootItem${index}`);
    const dropdown = document.getElementById(`lootItemDropdown${index}`);
    const searchTerm = input.value.toLowerCase();
    
    dropdown.innerHTML = '';
    dropdown.style.display = 'block';
    
    const filtered = availableItems.filter(item => 
        item.id.toLowerCase().includes(searchTerm) ||
        (item.name && item.name.toLowerCase().includes(searchTerm)) ||
        (item.emoji && item.emoji.includes(searchTerm))
    );
    
    if (filtered.length === 0) {
        dropdown.innerHTML = '<div style="padding: 8px; opacity: 0.5;">No items found</div>';
        return;
    }
    
    filtered.forEach(item => {
        const option = document.createElement('div');
        option.className = 'dropdown-item';
        option.style.padding = '8px';
        option.style.cursor = 'pointer';
        option.style.borderBottom = '1px solid #2a2a4a';
        option.innerHTML = `${item.emoji || '📦'} ${item.name || item.id} <span style="opacity: 0.6; font-size: 0.9em;">(${item.id})</span>`;
        
        // Add hover effects
        option.addEventListener('mouseover', function() {
            this.style.background = '#2a2a4a';
        });
        option.addEventListener('mouseout', function() {
            this.style.background = 'transparent';
        });
        
        option.addEventListener('click', () => {
            input.value = item.id;
            dropdown.style.display = 'none';
        });
        dropdown.appendChild(option);
    });
}

function showNPCCorpseItemDropdown(index) {
    filterNPCCorpseItemDropdown(index);
}

function filterNPCCorpseItemDropdown(index) {
    const input = document.getElementById(`corpseItem${index}`);
    const dropdown = document.getElementById(`corpseItemDropdown${index}`);
    const searchTerm = input.value.toLowerCase();
    
    dropdown.innerHTML = '';
    dropdown.style.display = 'block';
    
    const filtered = availableItems.filter(item => 
        item.id.toLowerCase().includes(searchTerm) ||
        (item.name && item.name.toLowerCase().includes(searchTerm)) ||
        (item.emoji && item.emoji.includes(searchTerm))
    );
    
    if (filtered.length === 0) {
        dropdown.innerHTML = '<div style="padding: 8px; opacity: 0.5;">No items found</div>';
        return;
    }
    
    filtered.forEach(item => {
        const option = document.createElement('div');
        option.className = 'dropdown-item';
        option.style.padding = '8px';
        option.style.cursor = 'pointer';
        option.style.borderBottom = '1px solid #2a2a4a';
        option.innerHTML = `${item.emoji || '📦'} ${item.name || item.id} <span style="opacity: 0.6; font-size: 0.9em;">(${item.id})</span>`;
        
        // Add hover effects
        option.addEventListener('mouseover', function() {
            this.style.background = '#2a2a4a';
        });
        option.addEventListener('mouseout', function() {
            this.style.background = 'transparent';
        });
        
        option.addEventListener('click', () => {
            input.value = item.id;
            dropdown.style.display = 'none';
        });
        dropdown.appendChild(option);
    });
}

// Hide dropdowns when clicking outside
document.addEventListener('click', function(e) {
    if (!e.target.matches('[id^="lootItem"], [id^="corpseItem"]')) {
        document.querySelectorAll('.item-dropdown').forEach(dropdown => {
            dropdown.style.display = 'none';
        });
    }
});

function addNPCLoot() {
    const npc = availableNPCs.find(n => n.id === selectedNPCId);
    if (!npc) return;
    
    if (!npc.loot_table) npc.loot_table = [];
    npc.loot_table.push({item_id: '', quantity_range: [1, 1], drop_chance: 0.5});
    renderNPCLootTable(npc.loot_table);
}

function removeNPCLoot(index) {
    const npc = availableNPCs.find(n => n.id === selectedNPCId);
    if (!npc || !npc.loot_table) return;
    
    npc.loot_table.splice(index, 1);
    renderNPCLootTable(npc.loot_table);
}

function addNPCCorpseLoot() {
    const npc = availableNPCs.find(n => n.id === selectedNPCId);
    if (!npc) return;
    
    if (!npc.corpse_loot) npc.corpse_loot = [];
    npc.corpse_loot.push({item_id: '', quantity: 1});
    renderNPCCorpseLoot(npc.corpse_loot);
}

function removeNPCCorpseLoot(index) {
    const npc = availableNPCs.find(n => n.id === selectedNPCId);
    if (!npc || !npc.corpse_loot) return;
    
    npc.corpse_loot.splice(index, 1);
    renderNPCCorpseLoot(npc.corpse_loot);
}

async function deleteCurrentNPC() {
    if (!selectedNPCId) return;
    
    if (!confirm(`Delete NPC "${selectedNPCId}"? This cannot be undone.`)) {
        return;
    }
    
    try {
        const response = await fetch(`/api/editor/npc/${selectedNPCId}`, {
            method: 'DELETE',
            credentials: 'same-origin'
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('NPC deleted successfully!');
            selectedNPCId = null;
            document.getElementById('npcEditor').innerHTML = '<div style="text-align: center; opacity: 0.5; padding: 50px;"><h3>Select an NPC or create a new one</h3></div>';
            await loadNPCManagement();
        } else {
            alert('Failed to delete: ' + data.error);
        }
    } catch (error) {
        alert('Failed to delete NPC: ' + error.message);
    }
}

// ==================== ITEM MANAGEMENT ====================

async function loadItemManagement() {
    try {
        const response = await fetch('/api/editor/items', {
            credentials: 'same-origin'
        });
        const data = await response.json();
        availableItems = data.items || [];
        renderItemManagementList();
    } catch (error) {
        console.error('Failed to load items:', error);
    }
}

function renderItemManagementList() {
    const list = document.getElementById('itemManagementList');
    list.innerHTML = '';
    
    availableItems.forEach(item => {
        const elem = document.createElement('div');
        elem.className = 'management-item';
        elem.dataset.name = item.name;
        elem.dataset.id = item.id;
        if (item.id === selectedItemId) {
            elem.classList.add('active');
        }
        
        elem.innerHTML = `
            <div><strong>${item.emoji ? item.emoji + ' ' : ''}${item.name}</strong></div>
            <div style="font-size: 0.85em; opacity: 0.7; margin-top: 5px;">
                Type: ${item.type} | Weight: ${item.weight}kg
            </div>
        `;
        
        elem.onclick = () => selectItem(item.id);
        list.appendChild(elem);
    });
}

function filterItemManagementList() {
    const searchTerm = document.getElementById('itemManagementSearch').value.toLowerCase();
    const items = document.querySelectorAll('#itemManagementList .management-item');
    
    items.forEach(item => {
        const name = item.dataset.name?.toLowerCase() || '';
        const id = item.dataset.id?.toLowerCase() || '';
        item.style.display = (!searchTerm || name.includes(searchTerm) || id.includes(searchTerm)) ? '' : 'none';
    });
}

function selectItem(itemId) {
    selectedItemId = itemId;
    renderItemManagementList();
    
    const item = availableItems.find(i => i.id === itemId);
    if (!item) return;
    
    const editor = document.getElementById('itemEditor');
    editor.innerHTML = `
        <h2>Edit Item: ${item.name}</h2>
        
        <div class="form-grid">
            <div class="property-group">
                <label>ID</label>
                <input type="text" id="itemId" value="${item.id}" readonly style="opacity: 0.6;">
            </div>
            <div class="property-group">
                <label>Name</label>
                <input type="text" id="itemName" value="${item.name}">
            </div>
            <div class="property-group">
                <label>Emoji</label>
                <input type="text" id="itemEmoji" value="${item.emoji || ''}" maxlength="2">
            </div>
        </div>
        
        <div class="form-grid">
            <div class="property-group">
                <label>Type</label>
                <select id="itemType">
                    <option value="resource" ${item.type === 'resource' ? 'selected' : ''}>Resource</option>
                    <option value="consumable" ${item.type === 'consumable' ? 'selected' : ''}>Consumable</option>
                    <option value="weapon" ${item.type === 'weapon' ? 'selected' : ''}>Weapon</option>
                    <option value="equipment" ${item.type === 'equipment' ? 'selected' : ''}>Equipment</option>
                    <option value="quest" ${item.type === 'quest' ? 'selected' : ''}>Quest Item</option>
                </select>
            </div>
            <div class="property-group">
                <label>Stackable</label>
                <select id="itemStackable">
                    <option value="true" ${item.stackable !== false ? 'selected' : ''}>Yes</option>
                    <option value="false" ${item.stackable === false ? 'selected' : ''}>No</option>
                </select>
            </div>
        </div>
        
        <div class="form-grid">
            <div class="property-group">
                <label>Weight (kg)</label>
                <input type="number" id="itemWeight" value="${item.weight}" step="0.1" min="0">
            </div>
            <div class="property-group">
                <label>Volume</label>
                <input type="number" id="itemVolume" value="${item.volume}" step="0.1" min="0">
            </div>
        </div>
        
        <div class="property-group">
            <label>Description</label>
            <textarea id="itemDescription" rows="3" style="width: 100%;">${item.description || ''}</textarea>
        </div>
        
        <h3 style="color: #ffa726; margin: 30px 0 15px;">Properties</h3>
        
        <div class="form-grid">
            <div class="property-group">
                <label>HP Restore</label>
                <input type="number" id="itemHpRestore" value="${item.hp_restore || 0}" min="0">
            </div>
            <div class="property-group">
                <label>Stamina Restore</label>
                <input type="number" id="itemStaminaRestore" value="${item.stamina_restore || 0}" min="0">
            </div>
        </div>
        
        <div class="form-grid">
            <div class="property-group">
                <label>Damage</label>
                <input type="number" id="itemDamage" value="${item.damage || 0}" min="0">
            </div>
            <div class="property-group">
                <label>Defense</label>
                <input type="number" id="itemDefense" value="${item.defense || 0}" min="0">
            </div>
        </div>
        
        <div class="form-grid">
            <div class="property-group">
                <label>Capacity Weight Bonus</label>
                <input type="number" id="itemCapacityWeight" value="${item.capacity_weight || 0}" min="0">
            </div>
            <div class="property-group">
                <label>Capacity Volume Bonus</label>
                <input type="number" id="itemCapacityVolume" value="${item.capacity_volume || 0}" min="0">
            </div>
        </div>
        
        <div class="property-group">
            <label style="display: flex; align-items: center; gap: 10px;">
                <input type="checkbox" id="itemStackable" ${item.stackable ? 'checked' : ''}>
                <span>Stackable</span>
            </label>
        </div>
        
        <div style="margin-top: 30px; padding-top: 20px; border-top: 2px solid #3a3a6a; display: flex; gap: 10px;">
            <button class="btn btn-danger" style="flex: 1;" onclick="deleteCurrentItem()">🗑️ Delete Item</button>
        </div>
    `;
}

function createNewItem() {
    const itemId = prompt('Enter Item ID (e.g., health_potion, iron_sword):');
    if (!itemId) return;
    
    const newItem = {
        id: itemId,
        name: 'New Item',
        emoji: '',
        type: 'resource',
        weight: 0.1,
        volume: 0.1,
        description: '',
        stackable: true,
        hp_restore: 0,
        stamina_restore: 0,
        damage: 0,
        defense: 0,
        capacity_weight: 0,
        capacity_volume: 0
    };
    
    availableItems.push(newItem);
    renderItemManagementList();
    selectItem(itemId);
}

async function saveCurrentItem_() {
    if (!selectedItemId) {
        alert('No item selected');
        return;
    }
    
    const itemData = {
        id: document.getElementById('itemId').value,
        name: document.getElementById('itemName').value,
        emoji: document.getElementById('itemEmoji').value,
        type: document.getElementById('itemType').value,
        weight: parseFloat(document.getElementById('itemWeight').value),
        volume: parseFloat(document.getElementById('itemVolume').value),
        description: document.getElementById('itemDescription').value,
        stackable: document.getElementById('itemStackable').value === 'true',
        hp_restore: parseInt(document.getElementById('itemHpRestore').value) || 0,
        stamina_restore: parseInt(document.getElementById('itemStaminaRestore').value) || 0,
        damage: parseInt(document.getElementById('itemDamage').value) || 0,
        defense: parseInt(document.getElementById('itemDefense').value) || 0,
        capacity_weight: parseInt(document.getElementById('itemCapacityWeight').value) || 0,
        capacity_volume: parseInt(document.getElementById('itemCapacityVolume').value) || 0
    };
    
    try {
        const response = await fetch('/api/editor/item', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            credentials: 'same-origin',
            body: JSON.stringify(itemData)
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Item saved successfully!');
            await loadItemManagement();
        } else {
            alert('Failed to save: ' + data.error);
        }
    } catch (error) {
        alert('Failed to save item: ' + error.message);
    }
}

async function deleteCurrentItem() {
    if (!selectedItemId) return;
    
    if (!confirm(`Delete item "${selectedItemId}"? This cannot be undone.`)) {
        return;
    }
    
    try {
        const response = await fetch(`/api/editor/item/${selectedItemId}`, {
            method: 'DELETE',
            credentials: 'same-origin'
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Item deleted successfully!');
            selectedItemId = null;
            document.getElementById('itemEditor').innerHTML = '<div style="text-align: center; opacity: 0.5; padding: 50px;"><h3>Select an item or create a new one</h3></div>';
            await loadItemManagement();
        } else {
            alert('Failed to delete: ' + data.error);
        }
    } catch (error) {
        alert('Failed to delete item: ' + error.message);
    }
}

// ==================== INTERACTABLES MANAGEMENT ====================

async function loadInteractableManagement() {
    try {
        const response = await fetch('/api/editor/interactables', {
            credentials: 'same-origin'
        });
        const data = await response.json();
        availableInteractables = data.interactables;
        renderInteractableManagementList();
    } catch (error) {
        console.error('Failed to load interactables:', error);
    }
}

function renderInteractableManagementList() {
    const list = document.getElementById('interactableManagementList');
    list.innerHTML = '';
    
    availableInteractables.forEach(inter => {
        const elem = document.createElement('div');
        elem.className = 'management-item';
        elem.dataset.name = inter.name;
        elem.dataset.id = inter.id;
        if (inter.id === selectedInteractableId) {
            elem.classList.add('active');
        }
        
        const actionCount = Object.keys(inter.actions || {}).length;
        elem.innerHTML = `
            <div><strong>${inter.name}</strong></div>
            <div style="font-size: 0.85em; opacity: 0.7; margin-top: 5px;">
                Actions: ${actionCount}
            </div>
        `;
        
        elem.onclick = () => selectInteractable(inter.id);
        list.appendChild(elem);
    });
}

function filterInteractableManagementList() {
    const searchTerm = document.getElementById('interactableManagementSearch').value.toLowerCase();
    const items = document.querySelectorAll('#interactableManagementList .management-item');
    
    items.forEach(item => {
        const name = item.dataset.name?.toLowerCase() || '';
        const id = item.dataset.id?.toLowerCase() || '';
        item.style.display = (!searchTerm || name.includes(searchTerm) || id.includes(searchTerm)) ? '' : 'none';
    });
}

function selectInteractable(interId) {
    selectedInteractableId = interId;
    renderInteractableManagementList();
    
    const inter = availableInteractables.find(i => i.id === interId);
    if (!inter) return;
    
    const editor = document.getElementById('interactableEditor');
    
    // Render actions
    let actionsHtml = '';
    for (const [actionId, action] of Object.entries(inter.actions || {})) {
        actionsHtml += `
            <div class="array-item" style="margin-bottom: 15px; position: relative;">
                <button class="btn btn-remove" style="position: absolute; top: 10px; right: 10px;" 
                        onclick="deleteInteractableAction('${actionId}')">× Remove</button>
                <h4 style="color: #ffa726; margin-bottom: 10px;">${action.label}</h4>
                <div class="form-grid">
                    <div class="property-group">
                        <label>Action ID</label>
                        <input type="text" value="${actionId}" readonly style="opacity: 0.6;">
                    </div>
                    <div class="property-group">
                        <label>Label</label>
                        <input type="text" class="action-label" data-action="${actionId}" value="${action.label}">
                    </div>
                    <div class="property-group">
                        <label>Stamina Cost</label>
                        <input type="number" class="action-stamina" data-action="${actionId}" value="${action.stamina_cost}" min="0">
                    </div>
                </div>
            </div>
        `;
    }
    
    editor.innerHTML = `
        <h2>Edit Interactable: ${inter.name}</h2>
        
        <div class="form-grid">
            <div class="property-group">
                <label>ID</label>
                <input type="text" id="interactableId" value="${inter.id}" readonly style="opacity: 0.6;">
            </div>
            <div class="property-group">
                <label>Name</label>
                <input type="text" id="interactableName" value="${inter.name}">
            </div>
        </div>
        
        <div class="property-group">
            <label>Description</label>
            <textarea id="interactableDescription" rows="3" style="width: 100%;">${inter.description || ''}</textarea>
        </div>
        
        <div class="property-group">
            <label>Interactable Image</label>
            <input type="text" id="interactableImagePath" value="${inter.image_path || ''}" 
                   placeholder="images/interactables/name.png"
                   oninput="updateInteractableImagePreview(this.value)">
            <div class="file-input-wrapper">
                <input type="file" id="interactableImageUpload" accept="image/*" onchange="uploadInteractableImage()">
                <label for="interactableImageUpload" class="file-input-label">📤 Upload New Image</label>
            </div>
            <div class="image-preview" id="interactableImagePreview">
                ${inter.image_path ? `<img src="/${inter.image_path}" alt="Interactable image" onerror="this.parentElement.innerHTML='<span>Image not found</span>'">` : '<span>No image</span>'}
            </div>
        </div>
        
        <h3 style="color: #ffa726; margin: 30px 0 15px;">Actions</h3>
        <div id="interactableActions">
            ${actionsHtml}
        </div>
        <button class="btn btn-add" onclick="addNewInteractableAction()" style="margin-top: 10px;">+ Add Action</button>
        
        <div style="margin-top: 30px; padding-top: 20px; border-top: 2px solid #3a3a6a; display: flex; gap: 10px;">
            <button class="btn btn-danger" style="flex: 1;" onclick="deleteCurrentInteractable()">🗑️ Delete Interactable</button>
        </div>
    `;
}

function createNewInteractable() {
    const interId = prompt('Enter Interactable ID (e.g., rubble, dumpster):');
    if (!interId) return;
    
    const newInteractable = {
        id: interId,
        name: 'New Interactable',
        description: '',
        image_path: '',
        actions: {
            'search': {
                id: 'search',
                label: '🔎 Search',
                stamina_cost: 2
            }
        }
    };
    
    availableInteractables.push(newInteractable);
    renderInteractableManagementList();
    selectInteractable(interId);
}

async function saveCurrentInteractable() {
    if (!selectedInteractableId) {
        alert('No interactable selected');
        return;
    }
    
    // Get basic fields
    const interData = {
        id: document.getElementById('interactableId').value,
        name: document.getElementById('interactableName').value,
        description: document.getElementById('interactableDescription').value,
        image_path: document.getElementById('interactableImagePath').value,
        actions: {}
    };
    
    // Get actions
    const inter = availableInteractables.find(i => i.id === selectedInteractableId);
    if (inter && inter.actions) {
        for (const [actionId, action] of Object.entries(inter.actions)) {
            const labelInput = document.querySelector(`.action-label[data-action="${actionId}"]`);
            const staminaInput = document.querySelector(`.action-stamina[data-action="${actionId}"]`);
            
            interData.actions[actionId] = {
                id: actionId,
                label: labelInput ? labelInput.value : action.label,
                stamina_cost: staminaInput ? parseInt(staminaInput.value) : action.stamina_cost
            };
        }
    }
    
    try {
        const response = await fetch('/api/editor/interactable', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            credentials: 'same-origin',
            body: JSON.stringify(interData)
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Interactable saved successfully!');
            await loadInteractableManagement();
        } else {
            alert('Failed to save: ' + data.error);
        }
    } catch (error) {
        alert('Failed to save interactable: ' + error.message);
    }
}

async function deleteCurrentInteractable() {
    if (!selectedInteractableId) {
        alert('No interactable selected');
        return;
    }
    
    if (!confirm(`Delete interactable "${selectedInteractableId}"?`)) {
        return;
    }
    
    try {
        const response = await fetch(`/api/editor/interactable/${selectedInteractableId}`, {
            method: 'DELETE',
            credentials: 'same-origin'
        });
        
        const data = await response.json();
        
        if (data.success) {
            showSuccess('Interactable deleted successfully!');
            selectedInteractableId = null;
            document.getElementById('interactableEditor').innerHTML = `
                <h3>Select an interactable to edit</h3>
                <p style="opacity: 0.7;">Choose from the list or create a new one.</p>
            `;
            await loadInteractableManagement();
        } else {
            alert('Failed to delete: ' + data.error);
        }
    } catch (error) {
        alert('Failed to delete interactable: ' + error.message);
    }
}

function updateInteractableImagePreview(imagePath) {
    const preview = document.getElementById('interactableImagePreview');
    if (imagePath && imagePath.trim()) {
        preview.innerHTML = `<img src="/${imagePath}" alt="Interactable image" onerror="this.parentElement.innerHTML='<span>Image not found</span>'">`;
    } else {
        preview.innerHTML = '<span>No image</span>';
    }
}

function addNewInteractableAction() {
    const actionId = prompt('Enter Action ID (e.g., search, break, open):');
    if (!actionId) return;
    
    const inter = availableInteractables.find(i => i.id === selectedInteractableId);
    if (!inter) return;
    
    // Check if action already exists
    if (inter.actions && inter.actions[actionId]) {
        alert('Action with this ID already exists!');
        return;
    }
    
    // Add new action
    if (!inter.actions) {
        inter.actions = {};
    }
    
    inter.actions[actionId] = {
        id: actionId,
        label: actionId.charAt(0).toUpperCase() + actionId.slice(1),
        stamina_cost: 2
    };
    
    // Re-render the editor
    selectInteractable(selectedInteractableId);
}

function deleteInteractableAction(actionId) {
    if (!confirm(`Delete action "${actionId}"?`)) {
        return;
    }
    
    const inter = availableInteractables.find(i => i.id === selectedInteractableId);
    if (!inter || !inter.actions) return;
    
    delete inter.actions[actionId];
    
    // Re-render the editor
    selectInteractable(selectedInteractableId);
}
