// Structure Builder JavaScript

// State management
let currentStructure = {
    name: "Untitled Structure",
    layers: [],
    superlattices: [],
    surface_params: {
        type: 'slope'
    },
    substrate_params: {
        type: 'slope'
    },
    mesh_spacing: 75.0
};

let selectedLayerIndex = -1;
let editingLayerIndex = -1;
let currentFilename = null;  // Track the currently loaded filename for saving

// License state
let isLicensed = false;
let demoConstraints = null;

function fetchLicenseStatus() {
    $.ajax({
        url: '/api/license/demo-constraints',
        method: 'GET',
        success: function(response) {
            isLicensed = response.is_licensed;
            demoConstraints = response.demo_constraints;
            updateLicenseBadge();
        },
        error: function() {
            isLicensed = false;
            demoConstraints = null;
            updateLicenseBadge();
        }
    });
}

function updateLicenseBadge() {
    // Remove existing badge
    $('#demoModeBadge').remove();

    if (!isLicensed) {
        // Add demo badge above the actions card
        const badge = $(`
            <div id="demoModeBadge" class="alert alert-warning alert-sm py-2 px-3 mb-2" style="font-size: 0.85rem;">
                <i class="bi bi-unlock"></i> <strong>Demo Mode</strong> —
                Max ${demoConstraints ? demoConstraints.max_layers : 3} layers,
                ${demoConstraints ? demoConstraints.allowed_materials.join(' & ') : 'GaAs & AlGaAs'} only.
                <a href="/license" class="alert-link">Activate license</a>
            </div>
        `);
        // Insert before the Actions card
        $('#runSimBtn').closest('.card').before(badge);
    }
}

/**
 * Client-side demo constraint check.
 * Returns { ok: true } or { ok: false, message: '...' }
 */
function checkDemoConstraints(layers, superlattices) {
    if (isLicensed || !demoConstraints) {
        return { ok: true };
    }

    // Check superlattices
    if (!demoConstraints.allow_superlattices && superlattices && superlattices.length > 0) {
        return { ok: false, message: 'Demo mode does not support superlattices. Activate a license to run this simulation.' };
    }

    // Check layer count
    if (layers.length > demoConstraints.max_layers) {
        return {
            ok: false,
            message: `Demo mode allows a maximum of ${demoConstraints.max_layers} layers (this structure has ${layers.length}). Activate a license to run this simulation.`
        };
    }

    // Check materials
    const allowed = demoConstraints.allowed_materials.map(m => m.toLowerCase());
    for (let i = 0; i < layers.length; i++) {
        const mat = (layers[i].material || '').toLowerCase();
        if (!allowed.includes(mat)) {
            return {
                ok: false,
                message: `Demo mode only allows ${demoConstraints.allowed_materials.join(' & ')} (layer ${i+1} uses "${layers[i].material}"). Activate a license to run this simulation.`
            };
        }
    }

    return { ok: true };
}

// Superlattice state
let currentSuperlattice = {
    layers: [],
    repetitions: 10,
    insertPosition: 'end'
};
let editingSLLayerIndex = -1;

// Initialize on page load
$(document).ready(function() {
    initializeBuilder();
    bindEvents();
});

function initializeBuilder() {
    updateLayerList();
    updateStructurePreview();
    updateTotalThickness();
    loadBoundaryConditions();
    updateTemperatureInfo();
    updateMeshPointsEstimate();

    // Load mesh spacing from structure
    if (currentStructure.mesh_spacing) {
        $('#meshSpacing').val(currentStructure.mesh_spacing);
    }

    // Fetch license status for demo mode checks
    fetchLicenseStatus();
}

function bindEvents() {
    // Add layer button
    $('#addLayerBtn').click(function() {
        showLayerModal(-1);
    });

    // Save layer button
    $('#saveLayerBtn').click(function() {
        saveLayer();
    });

    // Run simulation button
    $('#runSimBtn').click(function() {
        showSimulationSettings();
    });

    // Start simulation button
    $('#startSimBtn').click(function() {
        startSimulation();
    });

    // Save structure button
    $('#saveStructureBtn').click(function() {
        saveStructure();
    });

    // Export input button
    $('#exportInputBtn').click(function() {
        exportInputFile();
    });

    // Load structure button
    $('#loadStructureBtn').click(function() {
        showLoadStructureModal();
    });

    // Structure name change
    $('#structureName').on('input', function() {
        currentStructure.name = $(this).val();
    });

    // Show/hide Schrödinger parameters based on mode
    $('#simMode').change(function() {
        if ($(this).val() === 'schrodinger_poisson') {
            $('#schrodingerParams').show();
        } else {
            $('#schrodingerParams').hide();
        }
    });

    // Boundary condition event handlers
    bindBoundaryConditionEvents();

    // Voltage sweep event handlers
    $('#enableBiasSweep').change(function() {
        if ($(this).is(':checked')) {
            $('#biasSweepParams').slideDown();
            updateVoltageSweepCount();
        } else {
            $('#biasSweepParams').slideUp();
        }
    });

    $('#sweepStart, #sweepStop, #sweepStep').on('input', function() {
        updateVoltageSweepCount();
    });

    // Grading checkbox handler
    $('#enableGrading').change(function() {
        if ($(this).is(':checked')) {
            $('#singleCompositionDiv').hide();
            $('#gradedCompositionDiv').show();
        } else {
            $('#singleCompositionDiv').show();
            $('#gradedCompositionDiv').hide();
        }
    });

    // Material selection handler - enable composition only for ternary materials
    $('#layerMaterial').change(function() {
        updateCompositionFieldState($(this), '#layerComposition', '#compositionStart', '#compositionStop', '#enableGrading');
    });

    $('#slLayerMaterial').change(function() {
        updateCompositionFieldState($(this), '#slLayerComposition', null, null, null);
    });

    // Doping type handler - show density only when doping type is selected
    $('#layerDopingType').change(function() {
        updateDopingDensityFieldState($(this), '#layerDopingDensityDiv');
    });

    $('#slLayerDopingType').change(function() {
        updateDopingDensityFieldState($(this), '#slLayerDopingDensityDiv');
    });

    // Temperature change handlers
    $('#simTemperature, #tempUnit').on('input change', function() {
        updateTemperatureInfo();
    });

    // Mesh spacing change handler
    $('#meshSpacing').on('input', function() {
        let value = parseFloat($(this).val()) || 75.0;

        // Enforce minimum of 25Å to prevent crashes
        if (value < 25) {
            value = 25;
            $(this).val(25);
            showToast('Mesh spacing must be at least 25Å to prevent simulation crashes.', 'warning');
        }

        currentStructure.mesh_spacing = value;
        updateMeshPointsEstimate();
    });

    // Export handlers
    $('#exportInputBtn').click(function(e) {
        e.preventDefault();
        exportInputFile();
    });

    $('#exportJSONBtn').click(function(e) {
        e.preventDefault();
        exportStructureJSON();
    });

    $('#exportReportBtn').click(function(e) {
        e.preventDefault();
        showExportReportModal();
    });

    $('#generateReportBtn').click(function() {
        generateStructureReport();
    });

    // Superlattice handlers
    $('#addSuperlatticeBtn').click(function() {
        showSuperlatticeBuilder();
    });

    $('#slInsertPosition').change(function() {
        if ($(this).val() === 'custom') {
            $('#slCustomPositionDiv').slideDown();
        } else {
            $('#slCustomPositionDiv').slideUp();
        }
    });

    $('#addSLLayerBtn').click(function() {
        showSLLayerModal(-1);
    });

    $('#saveSLLayerBtn').click(function() {
        saveSLLayer();
    });

    $('#saveSuperlatticeBtn').click(function() {
        saveSuperlattice();
    });

    // Template buttons
    $('#slTemplateQW').click(function() {
        applySuperlatticeTemplate('qw');
    });

    $('#slTemplateDBR').click(function() {
        applySuperlatticeTemplate('dbr');
    });

    $('#slTemplateMQW').click(function() {
        applySuperlatticeTemplate('mqw');
    });

    $('#slRepetitions').on('input', function() {
        updateSLThickness();
    });

    // Fermi level grading checkbox handler
    $('#enableEfGrading').change(function() {
        if ($(this).is(':checked')) {
            $('#singleEfDiv').hide();
            $('#gradedEfDiv').show();
        } else {
            $('#singleEfDiv').show();
            $('#gradedEfDiv').hide();
        }
    });

    // Ion implant handlers
    $('#addImplantBtn').click(function() {
        addImplantEntry();
    });

    // C-V calculation toggle
    $('#enableCV').change(function() {
        if ($(this).is(':checked')) {
            $('#cvParams').slideDown();
            // Validate: surface must be Schottky
            if ($('#surfaceBCType').val() !== 'schottky') {
                showToast('C-V calculations require a Schottky barrier at the surface. Please update boundary conditions.', 'warning');
            }
            // Recommend enabling bias sweep
            if (!$('#enableBiasSweep').is(':checked')) {
                showToast('C-V curves require a voltage sweep. Consider enabling bias sweep.', 'info');
            }
        } else {
            $('#cvParams').slideUp();
        }
    });

    // Advanced convergence toggle
    $('#enableAdvConvergence').change(function() {
        $('#advConvergenceParams').toggle(this.checked);
    });
}

// =============================================================================
// Boundary Condition Functions
// =============================================================================

function bindBoundaryConditionEvents() {
    // Surface boundary type change
    $('#surfaceBCType').change(function() {
        updateSurfaceBoundaryUI();
        saveBoundaryConditions();
    });

    // Surface Schottky parameters
    $('#surfaceBarrierHeight').on('input', function() {
        saveBoundaryConditions();
    });

    // Surface voltage source
    $('#surfaceVoltageSource').change(function() {
        if ($(this).val()) {
            $('#surfaceVoltageValueDiv').show();
        } else {
            $('#surfaceVoltageValueDiv').hide();
        }
        saveBoundaryConditions();
    });

    $('#surfaceVoltageValue').on('input', function() {
        saveBoundaryConditions();
    });

    // Substrate boundary type change
    $('#substrateBCType').change(function() {
        updateSubstrateBoundaryUI();
        saveBoundaryConditions();
    });

    // Substrate Schottky parameters
    $('#substrateBarrierHeight').on('input', function() {
        saveBoundaryConditions();
    });

    // Substrate voltage source
    $('#substrateVoltageSource').change(function() {
        if ($(this).val()) {
            $('#substrateVoltageValueDiv').show();
        } else {
            $('#substrateVoltageValueDiv').hide();
        }
        saveBoundaryConditions();
    });

    $('#substrateVoltageValue').on('input', function() {
        saveBoundaryConditions();
    });
}

function updateSurfaceBoundaryUI() {
    const bcType = $('#surfaceBCType').val();

    // Hide all parameter divs first
    $('#surfaceSchottkyParams').hide();
    $('#surfaceVoltageParams').hide();

    // Show relevant parameters based on type
    if (bcType === 'schottky') {
        $('#surfaceSchottkyParams').show();
        $('#surfaceVoltageParams').show();
    } else if (bcType === 'ohmic') {
        $('#surfaceVoltageParams').show();
    }
}

function updateSubstrateBoundaryUI() {
    const bcType = $('#substrateBCType').val();

    // Hide all parameter divs first
    $('#substrateSchottkyParams').hide();
    $('#substrateVoltageParams').hide();

    // Show relevant parameters based on type
    if (bcType === 'schottky') {
        $('#substrateSchottkyParams').show();
        $('#substrateVoltageParams').show();
    } else if (bcType === 'ohmic') {
        $('#substrateVoltageParams').show();
    }
}

function saveBoundaryConditions() {
    // Save surface boundary conditions
    const surfaceType = $('#surfaceBCType').val();
    currentStructure.surface_params = {
        type: surfaceType
    };

    if (surfaceType === 'schottky') {
        currentStructure.surface_params.barrier_height = parseFloat($('#surfaceBarrierHeight').val()) || 0.6;
    }

    const surfaceVSource = $('#surfaceVoltageSource').val();
    if (surfaceVSource) {
        currentStructure.surface_params.voltage_source = surfaceVSource;
        currentStructure.surface_params.voltage_value = parseFloat($('#surfaceVoltageValue').val()) || 0.0;
    }

    // Save substrate boundary conditions
    const substrateType = $('#substrateBCType').val();
    currentStructure.substrate_params = {
        type: substrateType
    };

    if (substrateType === 'schottky') {
        currentStructure.substrate_params.barrier_height = parseFloat($('#substrateBarrierHeight').val()) || 0.6;
    }

    const substrateVSource = $('#substrateVoltageSource').val();
    if (substrateVSource) {
        currentStructure.substrate_params.voltage_source = substrateVSource;
        currentStructure.substrate_params.voltage_value = parseFloat($('#substrateVoltageValue').val()) || 0.0;
    }
}

function loadBoundaryConditions() {
    // Load surface boundary conditions
    const surfaceParams = currentStructure.surface_params || { type: 'slope' };
    $('#surfaceBCType').val(surfaceParams.type || 'slope');

    if (surfaceParams.barrier_height !== undefined) {
        $('#surfaceBarrierHeight').val(surfaceParams.barrier_height);
    }

    if (surfaceParams.voltage_source) {
        $('#surfaceVoltageSource').val(surfaceParams.voltage_source);
        $('#surfaceVoltageValue').val(surfaceParams.voltage_value || 0.0);
        $('#surfaceVoltageValueDiv').show();
    }

    updateSurfaceBoundaryUI();

    // Load substrate boundary conditions
    const substrateParams = currentStructure.substrate_params || { type: 'slope' };
    $('#substrateBCType').val(substrateParams.type || 'slope');

    if (substrateParams.barrier_height !== undefined) {
        $('#substrateBarrierHeight').val(substrateParams.barrier_height);
    }

    if (substrateParams.voltage_source) {
        $('#substrateVoltageSource').val(substrateParams.voltage_source);
        $('#substrateVoltageValue').val(substrateParams.voltage_value || 0.0);
        $('#substrateVoltageValueDiv').show();
    }

    updateSubstrateBoundaryUI();
}

// =============================================================================
// Temperature Control
// =============================================================================

// Temperature conversion and display
function updateTemperatureInfo() {
    const temp = parseFloat($('#simTemperature').val()) || 300;
    const unit = $('#tempUnit').val();

    let tempK, tempC;

    if (unit === 'K') {
        tempK = temp;
        tempC = temp - 273.15;
    } else {
        tempC = temp;
        tempK = temp + 273.15;
    }

    // Update info text
    $('#tempInfo').text(`${tempK.toFixed(1)} K = ${tempC.toFixed(1)} °C`);

    // Add special notes
    if (tempK < 100) {
        $('#tempInfo').append(' <span class="text-primary">(Cryogenic)</span>');
    } else if (Math.abs(tempK - 300) < 5) {
        $('#tempInfo').append(' <span class="text-success">(Room temperature)</span>');
    } else if (tempK > 400) {
        $('#tempInfo').append(' <span class="text-warning">(Elevated)</span>');
    }
}

// Set temperature from preset buttons
function setTemperature(value, unit) {
    $('#simTemperature').val(value);
    $('#tempUnit').val(unit);
    updateTemperatureInfo();
}

// =============================================================================
// Mesh Spacing Control
// =============================================================================

// Set mesh spacing from preset buttons
function setMeshSpacing(value) {
    $('#meshSpacing').val(value);
    currentStructure.mesh_spacing = value;
    updateMeshPointsEstimate();
}

// Update estimated number of mesh points
function updateMeshPointsEstimate() {
    const totalThickness = currentStructure.layers.reduce((sum, layer) => sum + layer.thickness, 0);
    const meshSpacing = parseFloat($('#meshSpacing').val()) || 75.0;

    if (totalThickness > 0) {
        // Convert thickness from nm to Angstroms
        const thicknessAngstroms = totalThickness * 10;
        const numPoints = Math.ceil(thicknessAngstroms / meshSpacing);

        $('#meshPointsEstimate').text(`Estimated mesh points: ${numPoints}`);
    } else {
        $('#meshPointsEstimate').text('');
    }
}

// =============================================================================
// Layer Management
// =============================================================================

function showLayerModal(index) {
    editingLayerIndex = index;

    if (index >= 0 && index < currentStructure.layers.length) {
        // Edit existing layer
        const layer = currentStructure.layers[index];
        $('#layerMaterial').val(layer.material);
        $('#layerThickness').val(layer.thickness);

        // Handle composition (single or graded)
        if (layer.composition_grading) {
            $('#enableGrading').prop('checked', true);
            $('#singleCompositionDiv').hide();
            $('#gradedCompositionDiv').show();
            $('#compositionStart').val(layer.composition_grading.start);
            $('#compositionStop').val(layer.composition_grading.stop);
        } else {
            $('#enableGrading').prop('checked', false);
            $('#singleCompositionDiv').show();
            $('#gradedCompositionDiv').hide();
            $('#layerComposition').val(layer.composition || '');
        }

        // Mesh spacing
        $('#layerMeshSpacing').val(layer.custom_params?.dy || '');

        // Shallow doping
        $('#layerDopingType').val(layer.doping_type || '');
        $('#layerDopingDensity').val(layer.doping_density || '');

        // Deep level doping
        $('#deepDonorConc').val(layer.deep_donor_concentration || '');
        $('#deepDonorEnergy').val(layer.deep_donor_energy || '');
        $('#deepAcceptorConc').val(layer.deep_acceptor_concentration || '');
        $('#deepAcceptorEnergy').val(layer.deep_acceptor_energy || '');

        // Per-layer carrier control
        $('#layerNoElectrons').prop('checked', layer.no_electrons || false);
        $('#layerNoHoles').prop('checked', layer.no_holes || false);
        if (layer.fully_ionized_layer === true) {
            $('#layerIonization').val('fullyionized');
        } else if (layer.fully_ionized_layer === false) {
            $('#layerIonization').val('ionize');
        } else {
            $('#layerIonization').val('');
        }

        // Fermi level
        if (layer.fermi_level_grading) {
            $('#enableEfGrading').prop('checked', true);
            $('#singleEfDiv').hide();
            $('#gradedEfDiv').show();
            $('#efStart').val(layer.fermi_level_grading.start);
            $('#efStop').val(layer.fermi_level_grading.stop);
            $('#layerFermiLevel').val('');
        } else {
            $('#enableEfGrading').prop('checked', false);
            $('#singleEfDiv').show();
            $('#gradedEfDiv').hide();
            $('#efStart').val('');
            $('#efStop').val('');
            $('#layerFermiLevel').val(layer.fermi_level != null ? layer.fermi_level : '');
        }

        // Polarization
        $('#layerPolarization').val(layer.polarization != null ? layer.polarization : '');

        // Material overrides
        const ov = layer.material_overrides || {};
        $('#overrideEr').val(ov.er || '');
        $('#overrideEg').val(ov.Eg || '');
        $('#overrideDeltaEc').val(ov.deltaEc || '');
        $('#overrideMe').val(ov.me || '');
        $('#overrideMhh').val(ov.mhh || '');
        $('#overrideMlh').val(ov.mlh || '');
        $('#overrideValley').val(ov.valley || '');

        // Collapse the overrides panel if no overrides are set
        if (Object.keys(ov).length > 0) {
            $('#materialOverridesCollapse').addClass('show');
        } else {
            $('#materialOverridesCollapse').removeClass('show');
        }

        $('#layerNote').val(layer.note || '');
    } else {
        // New layer - reset everything
        $('#layerForm')[0].reset();
        $('#enableGrading').prop('checked', false);
        $('#singleCompositionDiv').show();
        $('#gradedCompositionDiv').hide();
        $('#enableEfGrading').prop('checked', false);
        $('#singleEfDiv').show();
        $('#gradedEfDiv').hide();
        $('#layerNoElectrons').prop('checked', false);
        $('#layerNoHoles').prop('checked', false);
        $('#layerIonization').val('');
        $('#layerFermiLevel').val('');
        $('#layerPolarization').val('');
        $('#overrideEr').val('');
        $('#overrideEg').val('');
        $('#overrideDeltaEc').val('');
        $('#overrideMe').val('');
        $('#overrideMhh').val('');
        $('#overrideMlh').val('');
        $('#overrideValley').val('');
        $('#materialOverridesCollapse').removeClass('show');
    }

    // Update composition field state based on selected material
    updateCompositionFieldState($('#layerMaterial'), '#layerComposition', '#compositionStart', '#compositionStop', '#enableGrading');

    // Update doping density field visibility based on doping type
    updateDopingDensityFieldState($('#layerDopingType'), '#layerDopingDensityDiv');

    const modal = new bootstrap.Modal($('#layerModal')[0]);
    modal.show();
}

function saveLayer() {
    const layer = {
        material: $('#layerMaterial').val(),
        thickness: parseFloat($('#layerThickness').val()),
        doping_type: $('#layerDopingType').val() || null,
        doping_density: $('#layerDopingDensity').val() ? parseFloat($('#layerDopingDensity').val()) : null,
        note: $('#layerNote').val() || '',
        custom_params: {}
    };

    // Handle composition - either single or graded
    if ($('#enableGrading').is(':checked')) {
        const startX = parseFloat($('#compositionStart').val());
        const stopX = parseFloat($('#compositionStop').val());

        if (!isNaN(startX) && !isNaN(stopX)) {
            layer.composition_grading = {
                start: startX,
                stop: stopX
            };
            layer.composition = null;
        }
    } else {
        const comp = $('#layerComposition').val();
        layer.composition = comp ? parseFloat(comp) : null;
        layer.composition_grading = null;
    }

    // Custom mesh spacing
    const meshSpacing = $('#layerMeshSpacing').val();
    if (meshSpacing) {
        layer.custom_params.dy = parseFloat(meshSpacing);
    }

    // Deep level doping
    const deepDonorConc = $('#deepDonorConc').val();
    const deepDonorEnergy = $('#deepDonorEnergy').val();
    const deepAcceptorConc = $('#deepAcceptorConc').val();
    const deepAcceptorEnergy = $('#deepAcceptorEnergy').val();

    layer.deep_donor_concentration = deepDonorConc ? parseFloat(deepDonorConc) : null;
    layer.deep_donor_energy = deepDonorEnergy ? parseFloat(deepDonorEnergy) : null;
    layer.deep_acceptor_concentration = deepAcceptorConc ? parseFloat(deepAcceptorConc) : null;
    layer.deep_acceptor_energy = deepAcceptorEnergy ? parseFloat(deepAcceptorEnergy) : null;

    // Per-layer carrier control
    layer.no_electrons = $('#layerNoElectrons').is(':checked');
    layer.no_holes = $('#layerNoHoles').is(':checked');

    const ionization = $('#layerIonization').val();
    if (ionization === 'fullyionized') {
        layer.fully_ionized_layer = true;
    } else if (ionization === 'ionize') {
        layer.fully_ionized_layer = false;
    } else {
        layer.fully_ionized_layer = null;
    }

    // Fermi level - either single or graded
    if ($('#enableEfGrading').is(':checked')) {
        const efStart = parseFloat($('#efStart').val());
        const efStop = parseFloat($('#efStop').val());

        if (!isNaN(efStart) && !isNaN(efStop)) {
            layer.fermi_level_grading = {
                start: efStart,
                stop: efStop
            };
            layer.fermi_level = null;
        } else {
            layer.fermi_level_grading = null;
            layer.fermi_level = null;
        }
    } else {
        const ef = $('#layerFermiLevel').val();
        layer.fermi_level = ef !== '' ? parseFloat(ef) : null;
        layer.fermi_level_grading = null;
    }

    // Polarization
    const pol = $('#layerPolarization').val();
    layer.polarization = pol !== '' ? parseFloat(pol) : null;

    // Material property overrides
    layer.material_overrides = {};
    const overrideFields = {
        'overrideEr': 'er',
        'overrideEg': 'Eg',
        'overrideDeltaEc': 'deltaEc',
        'overrideMe': 'me',
        'overrideMhh': 'mhh',
        'overrideMlh': 'mlh',
        'overrideValley': 'valley'
    };

    for (const [fieldId, key] of Object.entries(overrideFields)) {
        const val = $(`#${fieldId}`).val();
        if (val !== '' && val !== null) {
            layer.material_overrides[key] = parseFloat(val);
        }
    }

    if (editingLayerIndex >= 0 && editingLayerIndex < currentStructure.layers.length) {
        currentStructure.layers[editingLayerIndex] = layer;
    } else {
        currentStructure.layers.push(layer);
    }

    updateLayerList();
    updateStructurePreview();
    updateTotalThickness();
    updateMeshPointsEstimate();

    safeHideModal('#layerModal');
}

function deleteLayer(index) {
    if (confirm('Are you sure you want to delete this layer?')) {
        currentStructure.layers.splice(index, 1);
        updateLayerList();
        updateStructurePreview();
        updateTotalThickness();
        updateMeshPointsEstimate();
    }
}

function moveLayerUp(index) {
    if (index > 0) {
        const temp = currentStructure.layers[index];
        currentStructure.layers[index] = currentStructure.layers[index - 1];
        currentStructure.layers[index - 1] = temp;
        updateLayerList();
        updateStructurePreview();
    }
}

function moveLayerDown(index) {
    if (index < currentStructure.layers.length - 1) {
        const temp = currentStructure.layers[index];
        currentStructure.layers[index] = currentStructure.layers[index + 1];
        currentStructure.layers[index + 1] = temp;
        updateLayerList();
        updateStructurePreview();
    }
}

// =============================================================================
// Superlattice Management
// =============================================================================

// Show superlattice builder
function showSuperlatticeBuilder() {
    // Reset superlattice state
    currentSuperlattice = {
        layers: [],
        repetitions: 10,
        insertPosition: 'end'
    };

    // Reset form
    $('#slRepetitions').val(10);
    $('#slInsertPosition').val('end');
    $('#slCustomPositionDiv').hide();

    // Update insert position options
    updateSLInsertPositions();

    // Clear layers list
    updateSLLayersList();

    const modal = new bootstrap.Modal($('#superlatticeModal')[0]);
    modal.show();
}

// Update insert position dropdown
function updateSLInsertPositions() {
    const $select = $('#slInsertPosition');
    const currentVal = $select.val();

    // Keep existing options
    $select.find('option[value="custom"]').remove();

    if (currentStructure.layers.length > 0) {
        $select.append('<option value="custom">Custom Position...</option>');
    }

    $select.val(currentVal);

    // Update max value for custom position
    $('#slCustomPosition').attr('max', currentStructure.layers.length);
}

// Show SL layer modal
function showSLLayerModal(index) {
    editingSLLayerIndex = index;

    if (index >= 0 && index < currentSuperlattice.layers.length) {
        // Edit existing layer
        const layer = currentSuperlattice.layers[index];
        $('#slLayerMaterial').val(layer.material);
        $('#slLayerThickness').val(layer.thickness);
        $('#slLayerComposition').val(layer.composition || '');
        $('#slLayerDopingType').val(layer.doping_type || '');
        $('#slLayerDopingDensity').val(layer.doping_density || '');
    } else {
        // New layer
        $('#slLayerForm')[0].reset();
    }

    // Update composition field state based on selected material
    updateCompositionFieldState($('#slLayerMaterial'), '#slLayerComposition', null, null, null);

    // Update doping density field visibility based on doping type
    updateDopingDensityFieldState($('#slLayerDopingType'), '#slLayerDopingDensityDiv');

    const modal = new bootstrap.Modal($('#slLayerModal')[0]);
    modal.show();
}

// Save SL layer
function saveSLLayer() {
    const layer = {
        material: $('#slLayerMaterial').val(),
        thickness: parseFloat($('#slLayerThickness').val()),
        composition: $('#slLayerComposition').val() ? parseFloat($('#slLayerComposition').val()) : null,
        doping_type: $('#slLayerDopingType').val() || null,
        doping_density: $('#slLayerDopingDensity').val() ? parseFloat($('#slLayerDopingDensity').val()) : null,
        note: '',
        custom_params: {}
    };

    if (editingSLLayerIndex >= 0 && editingSLLayerIndex < currentSuperlattice.layers.length) {
        currentSuperlattice.layers[editingSLLayerIndex] = layer;
    } else {
        currentSuperlattice.layers.push(layer);
    }

    updateSLLayersList();
    updateSLThickness();

    safeHideModal('#slLayerModal');
}

// Update SL layers list
function updateSLLayersList() {
    const $list = $('#slLayersList');
    $list.empty();

    if (currentSuperlattice.layers.length === 0) {
        $list.html(`
            <div class="text-muted text-center py-3">
                <i class="bi bi-inbox"></i><br>
                No layers added yet. Click "Add Layer" to start.
            </div>
        `);
        return;
    }

    currentSuperlattice.layers.forEach((layer, index) => {
        const composition = layer.composition !== null ? ` (x=${layer.composition})` : '';
        const doping = layer.doping_type && layer.doping_density !== null ?
            ` ${layer.doping_type}-${layer.doping_density.toExponential(1)}` : '';

        const item = $(`
            <div class="d-flex justify-content-between align-items-center border-bottom py-2">
                <div>
                    <strong>${layer.material}${composition}</strong>
                    <br>
                    <small class="text-muted">${layer.thickness} nm${doping}</small>
                </div>
                <div class="btn-group btn-group-sm" role="group">
                    <button class="btn btn-outline-secondary" onclick="moveSLLayerUp(${index})" title="Move Up">
                        <i class="bi bi-arrow-up"></i>
                    </button>
                    <button class="btn btn-outline-secondary" onclick="moveSLLayerDown(${index})" title="Move Down">
                        <i class="bi bi-arrow-down"></i>
                    </button>
                    <button class="btn btn-outline-primary" onclick="showSLLayerModal(${index})" title="Edit">
                        <i class="bi bi-pencil"></i>
                    </button>
                    <button class="btn btn-outline-danger" onclick="deleteSLLayer(${index})" title="Delete">
                        <i class="bi bi-trash"></i>
                    </button>
                </div>
            </div>
        `);

        $list.append(item);
    });
}

// Update SL thickness display
function updateSLThickness() {
    const periodThickness = currentSuperlattice.layers.reduce((sum, layer) => sum + layer.thickness, 0);
    const repetitions = parseInt($('#slRepetitions').val()) || 1;
    const totalThickness = periodThickness * repetitions;

    $('#slPeriodThickness').text(periodThickness.toFixed(2));
    $('#slTotalThickness').text(totalThickness.toFixed(2));
}

// Move SL layer up
function moveSLLayerUp(index) {
    if (index > 0) {
        const temp = currentSuperlattice.layers[index];
        currentSuperlattice.layers[index] = currentSuperlattice.layers[index - 1];
        currentSuperlattice.layers[index - 1] = temp;
        updateSLLayersList();
    }
}

// Move SL layer down
function moveSLLayerDown(index) {
    if (index < currentSuperlattice.layers.length - 1) {
        const temp = currentSuperlattice.layers[index];
        currentSuperlattice.layers[index] = currentSuperlattice.layers[index + 1];
        currentSuperlattice.layers[index + 1] = temp;
        updateSLLayersList();
    }
}

// Delete SL layer
function deleteSLLayer(index) {
    if (confirm('Remove this layer from the superlattice?')) {
        currentSuperlattice.layers.splice(index, 1);
        updateSLLayersList();
        updateSLThickness();
    }
}

// Save superlattice to structure
function saveSuperlattice() {
    if (currentSuperlattice.layers.length === 0) {
        alert('Please add at least one layer to the superlattice.');
        return;
    }

    const repetitions = parseInt($('#slRepetitions').val());
    if (repetitions < 1) {
        alert('Number of repetitions must be at least 1.');
        return;
    }

    // Determine insert position
    let insertPos = 0;
    const posType = $('#slInsertPosition').val();

    if (posType === 'end') {
        insertPos = currentStructure.layers.length;
    } else if (posType === 'start') {
        insertPos = 0;
    } else if (posType === 'custom') {
        insertPos = parseInt($('#slCustomPosition').val()) || 0;
    }

    // Create superlattice object
    const superlattice = {
        layers: currentSuperlattice.layers,
        repetitions: repetitions
    };

    // Add to structure
    if (!currentStructure.superlattices) {
        currentStructure.superlattices = [];
    }

    currentStructure.superlattices.push([insertPos, superlattice]);

    // Update displays
    updateLayerList();
    updateStructurePreview();
    updateTotalThickness();
    updateMeshPointsEstimate();

    safeHideModal('#superlatticeModal');

    showToast(`Superlattice added: ${repetitions} × ${currentSuperlattice.layers.length} layers = ${repetitions * currentSuperlattice.layers.length} total layers`, 'success');
}

// Apply superlattice templates
function applySuperlatticeTemplate(template) {
    if (template === 'qw') {
        // Quantum Well: GaAs well / AlGaAs barrier
        currentSuperlattice.layers = [
            {
                material: 'GaAs',
                thickness: 8.0,
                composition: null,
                doping_type: null,
                doping_density: null,
                note: 'Well',
                custom_params: {}
            },
            {
                material: 'AlGaAs',
                thickness: 10.0,
                composition: 0.3,
                doping_type: null,
                doping_density: null,
                note: 'Barrier',
                custom_params: {}
            }
        ];
        $('#slRepetitions').val(10);
    } else if (template === 'dbr') {
        // Distributed Bragg Reflector: Quarter-wave stack
        currentSuperlattice.layers = [
            {
                material: 'AlGaAs',
                thickness: 71.0,
                composition: 0.9,
                doping_type: null,
                doping_density: null,
                note: 'High index',
                custom_params: {}
            },
            {
                material: 'AlGaAs',
                thickness: 84.0,
                composition: 0.15,
                doping_type: null,
                doping_density: null,
                note: 'Low index',
                custom_params: {}
            }
        ];
        $('#slRepetitions').val(20);
    } else if (template === 'mqw') {
        // Multiple Quantum Wells
        currentSuperlattice.layers = [
            {
                material: 'InGaAs',
                thickness: 7.0,
                composition: 0.15,
                doping_type: null,
                doping_density: null,
                note: 'Well',
                custom_params: {}
            },
            {
                material: 'GaAs',
                thickness: 15.0,
                composition: null,
                doping_type: null,
                doping_density: null,
                note: 'Barrier',
                custom_params: {}
            }
        ];
        $('#slRepetitions').val(5);
    }

    updateSLLayersList();
    updateSLThickness();
}

// Delete superlattice
function deleteSuperlattice(slIndex) {
    if (!confirm('Delete this superlattice?')) return;

    if (currentStructure.superlattices && slIndex < currentStructure.superlattices.length) {
        currentStructure.superlattices.splice(slIndex, 1);
        updateLayerList();
        updateStructurePreview();
        updateTotalThickness();
        updateMeshPointsEstimate();
    }
}

// Move superlattice up
function moveSuperlatticeUp(slIndex) {
    if (slIndex > 0 && currentStructure.superlattices && slIndex < currentStructure.superlattices.length) {
        // Swap positions with previous superlattice
        const temp = currentStructure.superlattices[slIndex];
        currentStructure.superlattices[slIndex] = currentStructure.superlattices[slIndex - 1];
        currentStructure.superlattices[slIndex - 1] = temp;
        updateLayerList();
        updateStructurePreview();
        updateTotalThickness();
    }
}

// Move superlattice down
function moveSuperlatticeDown(slIndex) {
    if (currentStructure.superlattices && slIndex < currentStructure.superlattices.length - 1) {
        // Swap positions with next superlattice
        const temp = currentStructure.superlattices[slIndex];
        currentStructure.superlattices[slIndex] = currentStructure.superlattices[slIndex + 1];
        currentStructure.superlattices[slIndex + 1] = temp;
        updateLayerList();
        updateStructurePreview();
        updateTotalThickness();
    }
}

// =============================================================================
// UI Updates
// =============================================================================

function updateLayerList() {
    const $list = $('#layerList');
    $list.empty();

    if (currentStructure.layers.length === 0 &&
        (!currentStructure.superlattices || currentStructure.superlattices.length === 0)) {
        $list.html('<div class="alert alert-info">No layers added yet. Click "Add Layer" to start.</div>');
        return;
    }

    // Build combined list with layers and superlattices
    const items = [];

    // Add regular layers
    currentStructure.layers.forEach((layer, idx) => {
        items.push({
            type: 'layer',
            index: idx,
            data: layer
        });
    });

    // Insert superlattices at their positions
    if (currentStructure.superlattices) {
        currentStructure.superlattices.forEach(([pos, sl], slIdx) => {
            items.splice(pos, 0, {
                type: 'superlattice',
                slIndex: slIdx,
                data: sl
            });
        });
    }

    // Render items
    items.forEach((item, displayIdx) => {
        if (item.type === 'layer') {
            const layer = item.data;
            const idx = item.index;

            let composition = '';
            if (layer.composition_grading) {
                composition = ` (x=${layer.composition_grading.start}→${layer.composition_grading.stop})`;
            } else if (layer.composition !== null) {
                composition = ` (x=${layer.composition})`;
            }

            const doping = layer.doping_type && layer.doping_density !== null ?
                ` ${layer.doping_type}-${layer.doping_density.toExponential(1)}` : '';

            const meshInfo = layer.custom_params?.dy ?
                ` <span class="badge bg-info">dy=${layer.custom_params.dy}Å</span>` : '';

            const hasDeepLevels = (layer.deep_donor_concentration || layer.deep_acceptor_concentration);
            const deepLevelBadge = hasDeepLevels ?
                ' <span class="badge bg-warning text-dark" title="Has deep level doping"><i class="bi bi-layers-fill"></i> Deep</span>' : '';

            const itemDiv = $(`
                <div class="list-group-item layer-item" data-index="${idx}">
                    <div class="d-flex justify-content-between align-items-center">
                        <div>
                            <div class="layer-material">${layer.material}${composition}${meshInfo}${deepLevelBadge}</div>
                            <div class="layer-thickness">${layer.thickness} nm${doping}</div>
                            ${layer.note ? `<small class="text-muted">${layer.note}</small>` : ''}
                        </div>
                        <div class="layer-actions">
                            <button class="btn btn-sm btn-outline-primary me-1" onclick="moveLayerUp(${idx})" title="Move Up">
                                <i class="bi bi-arrow-up"></i>
                            </button>
                            <button class="btn btn-sm btn-outline-primary me-1" onclick="moveLayerDown(${idx})" title="Move Down">
                                <i class="bi bi-arrow-down"></i>
                            </button>
                            <button class="btn btn-sm btn-outline-secondary me-1" onclick="showLayerModal(${idx})" title="Edit">
                                <i class="bi bi-pencil"></i>
                            </button>
                            <button class="btn btn-sm btn-outline-danger" onclick="deleteLayer(${idx})" title="Delete">
                                <i class="bi bi-trash"></i>
                            </button>
                        </div>
                    </div>
                </div>
            `);

            $list.append(itemDiv);

        } else if (item.type === 'superlattice') {
            const sl = item.data;
            const slIdx = item.slIndex;
            const periodThickness = sl.layers.reduce((sum, l) => sum + l.thickness, 0);
            const totalThickness = periodThickness * sl.repetitions;

            const slDiv = $(`
                <div class="list-group-item bg-light border-start border-success border-3">
                    <div class="d-flex justify-content-between align-items-center">
                        <div>
                            <div class="fw-bold text-success">
                                <i class="bi bi-stack"></i> Superlattice (${sl.repetitions}× repetitions)
                            </div>
                            <small class="text-muted">
                                ${sl.layers.length} layers/period, ${periodThickness.toFixed(1)} nm/period
                                <br>
                                Total: ${totalThickness.toFixed(1)} nm
                            </small>
                        </div>
                        <div class="layer-actions">
                            <button class="btn btn-sm btn-outline-primary me-1" onclick="moveSuperlatticeUp(${slIdx})" title="Move Up">
                                <i class="bi bi-arrow-up"></i>
                            </button>
                            <button class="btn btn-sm btn-outline-primary me-1" onclick="moveSuperlatticeDown(${slIdx})" title="Move Down">
                                <i class="bi bi-arrow-down"></i>
                            </button>
                            <button class="btn btn-sm btn-outline-danger" onclick="deleteSuperlattice(${slIdx})" title="Delete">
                                <i class="bi bi-trash"></i>
                            </button>
                        </div>
                    </div>
                    <div class="mt-2 ps-3">
                        ${sl.layers.map(l => `<small>• ${l.material} ${l.thickness}nm</small>`).join('<br>')}
                    </div>
                </div>
            `);

            $list.append(slDiv);
        }
    });
}

function updateStructurePreview() {
    const $preview = $('#structurePreview');
    $preview.empty();

    if (currentStructure.layers.length === 0) {
        $preview.html('<div class="alert alert-secondary">No structure to preview</div>');
        return;
    }

    const totalThickness = currentStructure.layers.reduce((sum, layer) => sum + layer.thickness, 0);
    const maxWidth = $preview.width() || 600;

    const colors = {
        'GaAs': '#ff6b6b',
        'AlGaAs': '#4ecdc4',
        'AlAs': '#45b7d1',
        'InGaAs': '#f9ca24',
        'InAs': '#f0932b',
        'InP': '#6c5ce7'
    };

    currentStructure.layers.forEach((layer, index) => {
        const width = (layer.thickness / totalThickness) * maxWidth;
        const color = colors[layer.material] || '#95a5a6';

        const bar = $(`
            <div class="layer-bar" style="width: ${width}px; background-color: ${color};"
                 title="${layer.material} - ${layer.thickness} nm">
            </div>
        `);

        $preview.append(bar);
    });

    // Add labels
    const $labels = $('<div class="mt-2"></div>');
    currentStructure.layers.forEach((layer, index) => {
        $labels.append(`<div class="layer-label">${layer.material} (${layer.thickness} nm)</div>`);
    });
    $preview.append($labels);
}

function updateTotalThickness() {
    const total = currentStructure.layers.reduce((sum, layer) => sum + layer.thickness, 0);
    $('#totalThickness').text(total.toFixed(1));
}

// =============================================================================
// Voltage Sweep Functions
// =============================================================================

function populateVoltageSourcesList() {
    const $container = $('#voltageSourcesContainer');
    $container.empty();

    const voltageSources = [];

    // Check surface voltage source
    if (currentStructure.surface_params && currentStructure.surface_params.voltage_source) {
        voltageSources.push({
            name: currentStructure.surface_params.voltage_source,
            boundary: 'Surface',
            value: currentStructure.surface_params.voltage_value || 0.0
        });
    }

    // Check substrate voltage source
    if (currentStructure.substrate_params && currentStructure.substrate_params.voltage_source) {
        const vSource = currentStructure.substrate_params.voltage_source;
        // Don't duplicate if same as surface
        if (!voltageSources.find(v => v.name === vSource)) {
            voltageSources.push({
                name: vSource,
                boundary: 'Substrate',
                value: currentStructure.substrate_params.voltage_value || 0.0
            });
        }
    }

    if (voltageSources.length === 0) {
        $container.html('<p class="text-muted small mb-0">No voltage sources defined in boundary conditions.</p>');
        $('#voltageSourceCard').hide();
        return;
    }

    $('#voltageSourceCard').show();

    voltageSources.forEach(vs => {
        const sourceDiv = $(`
            <div class="mb-2 p-2 border rounded">
                <div class="d-flex justify-content-between align-items-center">
                    <div>
                        <strong>${vs.name}</strong>
                        <span class="badge bg-secondary">${vs.boundary}</span>
                    </div>
                    <div>
                        <span class="text-muted">Value:</span>
                        <span class="badge bg-primary">${vs.value} V</span>
                    </div>
                </div>
            </div>
        `);
        $container.append(sourceDiv);
    });
}

function populateVoltageSweepDropdown() {
    const $dropdown = $('#sweepVoltageSource');
    $dropdown.find('option:not(:first)').remove();

    const voltageSources = [];

    // Collect voltage sources from boundary conditions
    if (currentStructure.surface_params && currentStructure.surface_params.voltage_source) {
        voltageSources.push(currentStructure.surface_params.voltage_source);
    }

    if (currentStructure.substrate_params && currentStructure.substrate_params.voltage_source) {
        const vSource = currentStructure.substrate_params.voltage_source;
        if (!voltageSources.includes(vSource)) {
            voltageSources.push(vSource);
        }
    }

    voltageSources.forEach(vs => {
        $dropdown.append(`<option value="${vs}">${vs}</option>`);
    });

    // Auto-select if only one option
    if (voltageSources.length === 1) {
        $dropdown.val(voltageSources[0]);
    }
}

function updateVoltageSweepCount() {
    const start = parseFloat($('#sweepStart').val()) || 0;
    const stop = parseFloat($('#sweepStop').val()) || 0;
    const step = parseFloat($('#sweepStep').val()) || 0;

    if (step === 0) {
        $('#sweepStepCount').text('Invalid step (cannot be zero)');
        return;
    }

    // Calculate number of steps
    const numSteps = Math.floor(Math.abs((stop - start) / step)) + 1;

    if (numSteps < 1) {
        $('#sweepStepCount').text('Invalid range');
    } else if (numSteps > 100) {
        $('#sweepStepCount').html(`<span class="text-danger">${numSteps} (Warning: very large!)</span>`);
    } else {
        $('#sweepStepCount').text(numSteps);
    }
}

// =============================================================================
// Simulation
// =============================================================================

function showSimulationSettings() {
    if (currentStructure.layers.length === 0) {
        alert('Please add at least one layer before running a simulation.');
        return;
    }

    // Demo mode check
    const demoCheck = checkDemoConstraints(currentStructure.layers, currentStructure.superlattices);
    if (!demoCheck.ok) {
        showToast(demoCheck.message, 'warning', 8000);
        return;
    }

    // Reset batch editing mode
    batchEditingModel = null;
    $('#simSettingsModal .modal-title').html('<i class="bi bi-gear"></i> Simulation Settings');

    const defaultName = `sim`;
    $('#simName').val(defaultName);

    // Set default Schrödinger parameters
    const totalThickness = currentStructure.layers.reduce((sum, layer) => sum + layer.thickness, 0);
    const totalThicknessAngstroms = totalThickness * 10;

    $('#schrodingerStart').val(20);
    $('#schrodingerStop').attr('placeholder', `Auto (${Math.round(totalThicknessAngstroms * 0.9)} Å)`);
    $('#schrodingerStop').val('');

    // Show/hide Schrödinger params based on current mode
    if ($('#simMode').val() === 'schrodinger_poisson') {
        $('#schrodingerParams').show();
    } else {
        $('#schrodingerParams').hide();
    }

    // Set default temperature
    $('#simTemperature').val(300);
    $('#tempUnit').val('K');
    updateTemperatureInfo();

    // Populate voltage sources
    populateVoltageSourcesList();
    populateVoltageSweepDropdown();

    const modal = new bootstrap.Modal($('#simSettingsModal')[0]);
    // Load implants
    renderImplantList();

    // Restore settings from currentStructure (if previously set)
    if (currentStructure.convergence !== null && currentStructure.convergence !== undefined) {
        $('#enableAdvConvergence').prop('checked', true);
        $('#advConvergenceParams').show();
        $('#convergenceCriteria').val(currentStructure.convergence);
        $('#cvConvergenceCriteria').val(currentStructure.cv_convergence || 1e-10);
        $('#maxIterations').val(currentStructure.max_iterations || 100);
        $('#willRobinson').val(currentStructure.will_robinson || '');
    } else {
        $('#enableAdvConvergence').prop('checked', false);
        $('#advConvergenceParams').hide();
        $('#convergenceCriteria').val('1e-5');
        $('#cvConvergenceCriteria').val('1e-10');
        $('#maxIterations').val(100);
        $('#willRobinson').val('');
    }

    $('#globalNoElectrons').prop('checked', currentStructure.global_no_electrons || false);
    $('#globalNoHoles').prop('checked', currentStructure.global_no_holes || false);

    modal.show();
}

function startSimulation() {
    const simMode = $('#simMode').val();

    // Demo mode check (defence in depth — server also checks)
    const demoCheck2 = checkDemoConstraints(currentStructure.layers, currentStructure.superlattices);
    if (!demoCheck2.ok) {
        showToast(demoCheck2.message, 'warning', 8000);
        return;
    }

    // Name is auto-derived from structure name
    const simName = currentStructure.name || 'sim';

    // Validate mesh spacing
    const meshSpacing = parseFloat($('#meshSpacing').val()) || 75.0;
    if (meshSpacing < 25) {
        alert('Mesh spacing must be at least 25Å to prevent simulation crashes.\n\nPlease increase the mesh spacing.');
        return;
    }

    // Check for excessive mesh points
    const totalThickness = currentStructure.layers.reduce((sum, layer) => sum + layer.thickness, 0);
    const thicknessAngstroms = totalThickness * 10;
    const numPoints = Math.ceil(thicknessAngstroms / meshSpacing);

    if (numPoints > 2000) {
        alert(`ERROR: Too many mesh points (${numPoints})!\n\nThis will crash the simulation.\n\nPlease increase mesh spacing to at least ${Math.ceil(thicknessAngstroms / 2000)}Å.`);
        return;
    }

    if (numPoints > 1000) {
        if (!confirm(`WARNING: High number of mesh points (${numPoints}).\n\nThis simulation may take several minutes to complete.\n\nDo you want to continue?`)) {
            return;
        }
    }

    // Add Schrödinger parameters if in Schrödinger-Poisson mode
    if (simMode === 'schrodinger_poisson') {
        const schrodingerStart = parseInt($('#schrodingerStart').val()) || 20;
        const schrodingerStopVal = $('#schrodingerStop').val();
        const schrodingerStop = schrodingerStopVal ? parseInt(schrodingerStopVal) : null;

        currentStructure.schrodinger_params = {
            start: schrodingerStart,
            stop: schrodingerStop
        };
    } else {
        currentStructure.schrodinger_params = {};
    }

    // Get temperature in Kelvin
    const temp = parseFloat($('#simTemperature').val()) || 300;
    const unit = $('#tempUnit').val();
    const tempK = unit === 'K' ? temp : temp + 273.15;

    // Add voltage sweep parameters if enabled
    const voltageSweepData = {};
    if ($('#enableBiasSweep').is(':checked')) {
        const sweepSource = $('#sweepVoltageSource').val();

        if (!sweepSource) {
            alert('Please select a voltage source for the sweep.');
            return;
        }

        voltageSweepData.enabled = true;
        voltageSweepData.source = sweepSource;
        voltageSweepData.start = parseFloat($('#sweepStart').val()) || 0.0;
        voltageSweepData.stop = parseFloat($('#sweepStop').val()) || 0.0;
        voltageSweepData.step = parseFloat($('#sweepStep').val()) || -0.5;

        if (voltageSweepData.step === 0) {
            alert('Voltage step cannot be zero.');
            return;
        }
    } else {
        voltageSweepData.enabled = false;
    }

    // --- Advanced Convergence Settings ---
    if ($('#enableAdvConvergence').is(':checked')) {
        const conv = parseFloat($('#convergenceCriteria').val());
        if (!isNaN(conv) && conv > 0) {
            currentStructure.convergence = conv;
        }
        const cvConv = parseFloat($('#cvConvergenceCriteria').val());
        if (!isNaN(cvConv) && cvConv > 0) {
            currentStructure.cv_convergence = cvConv;
        }
        const maxIter = parseInt($('#maxIterations').val());
        if (!isNaN(maxIter) && maxIter > 0) {
            currentStructure.max_iterations = maxIter;
        }
        const wr = $('#willRobinson').val();
        currentStructure.will_robinson = wr || null;
    } else {
        currentStructure.convergence = null;
        currentStructure.cv_convergence = null;
        currentStructure.max_iterations = null;
        currentStructure.will_robinson = null;
    }

    // --- Global Carrier Control ---
    currentStructure.global_no_electrons = $('#globalNoElectrons').is(':checked');
    currentStructure.global_no_holes = $('#globalNoHoles').is(':checked');

    // Show loading
    const $btn = $('#startSimBtn');
    $btn.prop('disabled', true);
    $btn.html('<span class="spinner-border spinner-border-sm me-2"></span>Running...');

    // Create progress modal
    showProgressModal();

    // Send API request with monitoring enabled
    $.ajax({
        url: '/api/simulation/run',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            structure: currentStructure,
            name: simName,
            mode: simMode,
            temperature: tempK,
            monitor: true,
            voltage_sweep: voltageSweepData,
            cv_mode: $('#enableCV').is(':checked') ? ($('#cvMode').val() || 'cv') : null
        }),
        success: function(response) {
            if (response.success && response.monitoring) {
                monitorSimulation(response.sim_id, simName);
            } else {
                hideProgressModal();
                showToast('Simulation completed!', 'success');
                safeHideModal('#simSettingsModal');
                window.location.href = '/results';
            }
        },
        error: function(xhr) {
            hideProgressModal();
            const responseData = xhr.responseJSON || {};
            if (responseData.demo_restricted) {
                showToast(responseData.error, 'warning', 10000);
            } else {
                const error = responseData.error || 'Unknown error';
                alert('Simulation failed: ' + error);
            }
            $btn.prop('disabled', false);
            $btn.html('<i class="bi bi-play-circle"></i> Start Simulation');
        }
    });
}

function showProgressModal() {
    // Create progress modal if it doesn't exist
    if ($('#progressModal').length === 0) {
        $('body').append(`
            <div class="modal fade" id="progressModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
                <div class="modal-dialog">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">Simulation Progress</h5>
                        </div>
                        <div class="modal-body">
                            <div class="mb-3">
                                <div class="progress">
                                    <div class="progress-bar progress-bar-striped progress-bar-animated"
                                         id="progressBar" role="progressbar" style="width: 0%"></div>
                                </div>
                            </div>
                            <div id="progressMessage" class="text-center">
                                <i class="bi bi-hourglass-split"></i> Initializing...
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `);
    }

    // Reset and show
    $('#progressBar').css('width', '0%').text('0%');
    $('#progressMessage').html('<i class="bi bi-hourglass-split"></i> Initializing...');

    const modal = new bootstrap.Modal($('#progressModal')[0]);
    modal.show();
}

function hideProgressModal() {
    const modal = bootstrap.Modal.getInstance($('#progressModal')[0]);
    if (modal) {
        modal.hide();
    }
}

function monitorSimulation(simId, simName) {
    // Create EventSource for Server-Sent Events
    const eventSource = new EventSource(`/api/simulation/monitor/${simId}`);

    eventSource.onmessage = function(event) {
        const data = JSON.parse(event.data);

        if (data.status === 'alive') {
            // Keepalive message, ignore
            return;
        }

        // Update progress
        if (data.progress !== undefined) {
            $('#progressBar').css('width', data.progress + '%').text(data.progress + '%');
        }

        // Update message
        if (data.message) {
            let icon = '<i class="bi bi-hourglass-split"></i>';
            if (data.status === 'complete') {
                icon = '<i class="bi bi-check-circle text-success"></i>';
            } else if (data.status === 'failed' || data.status === 'error') {
                icon = '<i class="bi bi-x-circle text-danger"></i>';
            }

            $('#progressMessage').html(`${icon} ${data.message}`);
        }

        // Handle completion
        if (data.status === 'complete') {
            eventSource.close();
            setTimeout(function() {
                hideProgressModal();
                safeHideModal('#simSettingsModal');

                // Show success message and redirect
                showToast('Simulation completed!', 'success');
                setTimeout(function() {
                    window.location.href = '/results';
                }, 1500);
            }, 1500);
        } else if (data.status === 'failed' || data.status === 'error') {
            eventSource.close();
            setTimeout(function() {
                hideProgressModal();
                alert('Simulation failed: ' + data.message);
                $('#startSimBtn').prop('disabled', false);
                $('#startSimBtn').html('<i class="bi bi-play-circle"></i> Start Simulation');
            }, 1500);
        }
    };

    eventSource.onerror = function() {
        eventSource.close();
        hideProgressModal();
        alert('Lost connection to simulation monitor');
        $('#startSimBtn').prop('disabled', false);
        $('#startSimBtn').html('<i class="bi bi-play-circle"></i> Start Simulation');
    };
}

// =============================================================================
// Save/Load
// =============================================================================

function saveStructure() {
    // Capture current simulation settings (comprehensive)
    const simSettings = {
        temperature: parseFloat($('#simTemperature').val()) || 300.0,
        temp_unit: $('#tempUnit').val() || 'K',
        mode: $('#simMode').val() || 'poisson',
        mesh_spacing: parseFloat($('#meshSpacing').val()) || 75.0,
        voltage_sweep: {
            enabled: $('#enableBiasSweep').is(':checked'),
            source: $('#sweepVoltageSource').val() || 'v1',
            start: parseFloat($('#sweepStart').val()) || 0.0,
            stop: parseFloat($('#sweepStop').val()) || -2.0,
            step: parseFloat($('#sweepStep').val()) || -0.5
        },
        cv_mode: $('#enableCV').is(':checked') ? ($('#cvMode').val() || 'cv') : null,
        schrodinger_params: {
            start: parseFloat($('#schrodingerStart').val()) || 20,
            stop: $('#schrodingerStop').val() ? parseFloat($('#schrodingerStop').val()) : null
        },
        convergence: {
            criteria: $('#enableAdvConvergence').is(':checked') ?
                     (parseFloat($('#convergenceCriteria').val()) || 1e-5) : null,
            cv_criteria: $('#enableAdvConvergence').is(':checked') ?
                        (parseFloat($('#cvConvergenceCriteria').val()) || 1e-10) : null,
            max_iterations: $('#enableAdvConvergence').is(':checked') ?
                           (parseInt($('#maxIterations').val()) || 100) : null,
            will_robinson: $('#enableAdvConvergence').is(':checked') ?
                          ($('#willRobinson').val() || null) : null
        }
    };

    // Add settings to structure
    currentStructure.simulation_settings = simSettings;

    // Prepare data with optional filename to update existing file
    const saveData = { ...currentStructure };
    if (currentFilename) {
        saveData.filename = currentFilename;
    }

    $.ajax({
        url: '/api/structure/save',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(saveData),
        success: function(response) {
            if (response.success) {
                // Update current filename if it was newly generated
                if (!currentFilename && response.filename) {
                    currentFilename = response.filename;
                }
                showToast('Structure saved successfully!', 'success');
            } else {
                alert('Error saving structure: ' + response.error);
            }
        },
        error: function(xhr) {
            alert('Error saving structure: ' + (xhr.responseJSON?.error || 'Unknown error'));
        }
    });
}

function exportInputFile() {
    if (currentStructure.layers.length === 0) {
        alert('Please add at least one layer before exporting.');
        return;
    }

    $.ajax({
        url: '/api/structure/to_input',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(currentStructure),
        success: function(response) {
            if (response.success) {
                // Download as file
                const blob = new Blob([response.input_text], { type: 'text/plain' });
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `${currentStructure.name}.txt`;
                a.click();
                window.URL.revokeObjectURL(url);
            } else {
                alert('Error exporting: ' + response.error);
            }
        },
        error: function(xhr) {
            alert('Error exporting: ' + (xhr.responseJSON?.error || 'Unknown error'));
        }
    });
}

function showLoadStructureModal() {
    // Create modal if it doesn't exist
    if ($('#loadStructureModal').length === 0) {
        $('body').append(`
            <div class="modal fade" id="loadStructureModal" tabindex="-1">
                <div class="modal-dialog modal-lg">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">Load Structure</h5>
                            <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                        </div>
                        <div class="modal-body">
                            <div id="structureListContainer">
                                <div class="text-center">
                                    <div class="spinner-border" role="status">
                                        <span class="visually-hidden">Loading...</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `);
    }

    // Show modal
    const modal = new bootstrap.Modal($('#loadStructureModal')[0]);
    modal.show();

    // Load structure list
    loadStructureList();
}

function loadStructureList() {
    $.ajax({
        url: '/api/structure/list',
        method: 'GET',
        success: function(response) {
            if (response.success) {
                displayStructureList(response.structures);
            } else {
                $('#structureListContainer').html(
                    '<div class="alert alert-danger">Error loading structures: ' + response.error + '</div>'
                );
            }
        },
        error: function(xhr) {
            $('#structureListContainer').html(
                '<div class="alert alert-danger">Error loading structures: ' +
                (xhr.responseJSON?.error || 'Unknown error') + '</div>'
            );
        }
    });
}

function displayStructureList(structures) {
    const $container = $('#structureListContainer');

    if (structures.length === 0) {
        $container.html('<div class="alert alert-info">No saved structures found. Save a structure first!</div>');
        return;
    }

    let html = '<div class="list-group">';
    structures.forEach(function(structure) {
        const date = new Date(structure.timestamp * 1000).toLocaleString();
        html += `
            <a href="#" class="list-group-item list-group-item-action" onclick="loadStructureFromFile('${structure.filename}'); return false;">
                <div class="d-flex w-100 justify-content-between">
                    <h6 class="mb-1">${structure.name}</h6>
                    <small>${date}</small>
                </div>
                <p class="mb-1">
                    <i class="bi bi-layers"></i> ${structure.layer_count} layer(s)
                </p>
                <small class="text-muted">${structure.filename}</small>
            </a>
        `;
    });
    html += '</div>';

    $container.html(html);
}

function loadStructureFromFile(filename) {
    $.ajax({
        url: '/api/structure/load',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({ filename: filename }),
        success: function(response) {
            if (response.success) {
                currentStructure = response.structure;
                currentFilename = filename;  // Track the loaded filename
                $('#structureName').val(currentStructure.name);

                // Load simulation settings if available (prioritize these over root-level values)
                if (currentStructure.simulation_settings) {
                    const settings = currentStructure.simulation_settings;

                    // Temperature
                    $('#simTemperature').val(settings.temperature !== undefined ? settings.temperature : 300.0);
                    $('#tempUnit').val(settings.temp_unit || 'K');

                    // Mode
                    $('#simMode').val(settings.mode || 'poisson');

                    // Show/hide Schrödinger params based on loaded mode
                    if (settings.mode === 'schrodinger_poisson') {
                        $('#schrodingerParams').show();
                    } else {
                        $('#schrodingerParams').hide();
                    }

                    // Mesh spacing - ALWAYS prioritize simulation_settings if present
                    let meshSpacingToUse;
                    if (settings.hasOwnProperty('mesh_spacing') && settings.mesh_spacing !== null) {
                        // Use value from simulation settings
                        meshSpacingToUse = settings.mesh_spacing;
                    } else if (currentStructure.mesh_spacing !== undefined && currentStructure.mesh_spacing !== null) {
                        // Fall back to root level
                        meshSpacingToUse = currentStructure.mesh_spacing;
                    } else {
                        // Use default
                        meshSpacingToUse = 75.0;
                    }

                    $('#meshSpacing').val(meshSpacingToUse);
                    currentStructure.mesh_spacing = meshSpacingToUse;

                    // Voltage sweep - use proper null checks
                    if (settings.voltage_sweep) {
                        $('#enableBiasSweep').prop('checked', !!settings.voltage_sweep.enabled);
                        $('#sweepVoltageSource').val(settings.voltage_sweep.source || 'v1');
                        $('#sweepStart').val(settings.voltage_sweep.start !== undefined ? settings.voltage_sweep.start : 0.0);
                        $('#sweepStop').val(settings.voltage_sweep.stop !== undefined ? settings.voltage_sweep.stop : -2.0);
                        $('#sweepStep').val(settings.voltage_sweep.step !== undefined ? settings.voltage_sweep.step : -0.5);

                        // Show/hide sweep controls
                        if (settings.voltage_sweep.enabled) {
                            $('#biasSweepParams').show();
                        } else {
                            $('#biasSweepParams').hide();
                        }
                    } else {
                        $('#enableBiasSweep').prop('checked', false);
                        $('#biasSweepParams').hide();
                    }

                    // CV mode
                    if (settings.cv_mode) {
                        $('#enableCV').prop('checked', true);
                        $('#cvMode').val(settings.cv_mode);
                        $('#cvParams').show();
                    } else {
                        $('#enableCV').prop('checked', false);
                        $('#cvParams').hide();
                    }

                    // Schrödinger parameters
                    if (settings.schrodinger_params) {
                        $('#schrodingerStart').val(settings.schrodinger_params.start !== undefined ? settings.schrodinger_params.start : 20);
                        if (settings.schrodinger_params.stop !== undefined && settings.schrodinger_params.stop !== null) {
                            $('#schrodingerStop').val(settings.schrodinger_params.stop);
                        } else {
                            $('#schrodingerStop').val('');
                        }
                    } else {
                        $('#schrodingerStart').val(20);
                        $('#schrodingerStop').val('');
                    }

                    // Convergence parameters
                    if (settings.convergence) {
                        const hasConvergenceSettings =
                            (settings.convergence.criteria !== null && settings.convergence.criteria !== undefined) ||
                            (settings.convergence.cv_criteria !== null && settings.convergence.cv_criteria !== undefined) ||
                            (settings.convergence.max_iterations !== null && settings.convergence.max_iterations !== undefined) ||
                            settings.convergence.will_robinson;

                        if (hasConvergenceSettings) {
                            $('#enableAdvConvergence').prop('checked', true);
                            $('#advConvergenceParams').show();

                            if (settings.convergence.criteria !== undefined && settings.convergence.criteria !== null)
                                $('#convergenceCriteria').val(settings.convergence.criteria);
                            if (settings.convergence.cv_criteria !== undefined && settings.convergence.cv_criteria !== null)
                                $('#cvConvergenceCriteria').val(settings.convergence.cv_criteria);
                            if (settings.convergence.max_iterations !== undefined && settings.convergence.max_iterations !== null)
                                $('#maxIterations').val(settings.convergence.max_iterations);
                            if (settings.convergence.will_robinson)
                                $('#willRobinson').val(settings.convergence.will_robinson);
                        } else {
                            $('#enableAdvConvergence').prop('checked', false);
                            $('#advConvergenceParams').hide();
                        }
                    } else {
                        $('#enableAdvConvergence').prop('checked', false);
                        $('#advConvergenceParams').hide();
                    }
                } else {
                    // No simulation settings - set all to defaults
                    $('#simTemperature').val(300.0);
                    $('#tempUnit').val('K');
                    $('#simMode').val('poisson');
                    $('#meshSpacing').val(currentStructure.mesh_spacing || 75.0);
                    $('#schrodingerParams').hide();  // Hide Schrödinger params for Poisson-only default
                    $('#enableBiasSweep').prop('checked', false);
                    $('#biasSweepParams').hide();
                    $('#enableCV').prop('checked', false);
                    $('#cvParams').hide();
                    $('#schrodingerStart').val(20);
                    $('#schrodingerStop').val('');
                    $('#enableAdvConvergence').prop('checked', false);
                    $('#advConvergenceParams').hide();
                }

                updateLayerList();
                updateStructurePreview();
                updateTotalThickness();
                loadBoundaryConditions();
                updateMeshPointsEstimate();

                // Safely hide modal by removing focus first
                safeHideModal('#loadStructureModal');
                showToast('Structure loaded successfully!', 'success');
            } else {
                alert('Error loading structure: ' + response.error);
            }
        },
        error: function(xhr) {
            alert('Error loading structure: ' + (xhr.responseJSON?.error || 'Unknown error'));
        }
    });
}

// Export structure as JSON
function exportStructureJSON() {
    if (currentStructure.layers.length === 0) {
        alert('Please add at least one layer before exporting.');
        return;
    }

    const jsonStr = JSON.stringify(currentStructure, null, 2);
    const blob = new Blob([jsonStr], { type: 'application/json' });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${currentStructure.name}.json`;
    a.click();
    window.URL.revokeObjectURL(url);
}

// Show export report modal
function showExportReportModal() {
    if (currentStructure.layers.length === 0) {
        alert('Please add at least one layer before generating a report.');
        return;
    }

    const modal = new bootstrap.Modal($('#exportReportModal')[0]);
    modal.show();
}

// Generate structure report
function generateStructureReport() {
    const format = $('#reportFormat').val();
    const includeLayerTable = $('#includeLayerTable').is(':checked');
    const includeBoundaryConditions = $('#includeBoundaryConditions').is(':checked');
    const includeInputFile = $('#includeInputFile').is(':checked');
    const includeValidation = $('#includeValidation').is(':checked');

    let report = '';

    if (format === 'html') {
        report = generateHTMLReport(includeLayerTable, includeBoundaryConditions, includeInputFile, includeValidation);
    } else if (format === 'markdown') {
        report = generateMarkdownReport(includeLayerTable, includeBoundaryConditions, includeInputFile, includeValidation);
    } else {
        report = generateTextReport(includeLayerTable, includeBoundaryConditions, includeInputFile, includeValidation);
    }

    // Download report
    const mimeTypes = {
        'html': 'text/html',
        'markdown': 'text/markdown',
        'text': 'text/plain'
    };

    const extensions = {
        'html': 'html',
        'markdown': 'md',
        'text': 'txt'
    };

    const blob = new Blob([report], { type: mimeTypes[format] });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${currentStructure.name}_report.${extensions[format]}`;
    a.click();
    window.URL.revokeObjectURL(url);

    safeHideModal('#exportReportModal');
}

// Generate HTML report
function generateHTMLReport(includeLayerTable, includeBoundaryConditions, includeInputFile, includeValidation) {
    let html = `<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>${currentStructure.name} - Structure Report</title>
    <style>
        body {
            font-family: 'Segoe UI', Arial, sans-serif;
            max-width: 900px;
            margin: 40px auto;
            padding: 20px;
            line-height: 1.6;
        }
        h1 { color: #0d6efd; border-bottom: 3px solid #0d6efd; padding-bottom: 10px; }
        h2 { color: #495057; border-bottom: 1px solid #dee2e6; padding-bottom: 5px; margin-top: 30px; }
        table { border-collapse: collapse; width: 100%; margin: 20px 0; }
        th, td { border: 1px solid #dee2e6; padding: 8px 12px; text-align: left; }
        th { background-color: #f8f9fa; font-weight: 600; }
        tr:nth-child(even) { background-color: #f8f9fa; }
        .info-box { background-color: #e7f3ff; border-left: 4px solid #0d6efd; padding: 15px; margin: 20px 0; }
        .warning-box { background-color: #fff3cd; border-left: 4px solid #ffc107; padding: 15px; margin: 20px 0; }
        pre { background-color: #f8f9fa; padding: 15px; border-radius: 5px; overflow-x: auto; }
        .badge { display: inline-block; padding: 3px 8px; border-radius: 3px; font-size: 0.85em; }
        .badge-info { background-color: #0dcaf0; color: white; }
        .badge-warning { background-color: #ffc107; color: #000; }
    </style>
</head>
<body>
    <h1>${currentStructure.name}</h1>
    <p><strong>Generated:</strong> ${new Date().toLocaleString()}</p>

    <div class="info-box">
        <strong>Total Thickness:</strong> ${currentStructure.layers.reduce((sum, l) => sum + l.thickness, 0).toFixed(2)} nm<br>
        <strong>Number of Layers:</strong> ${currentStructure.layers.length}
    </div>
`;

    if (includeLayerTable) {
        html += `
    <h2>Layer Structure</h2>
    <table>
        <thead>
            <tr>
                <th>#</th>
                <th>Material</th>
                <th>Thickness (nm)</th>
                <th>Composition</th>
                <th>Doping</th>
                <th>Notes</th>
            </tr>
        </thead>
        <tbody>
`;
        currentStructure.layers.forEach((layer, idx) => {
            let composition = '-';
            if (layer.composition_grading) {
                composition = `x=${layer.composition_grading.start}→${layer.composition_grading.stop}`;
            } else if (layer.composition !== null) {
                composition = `x=${layer.composition}`;
            }

            let doping = '-';
            if (layer.doping_type && layer.doping_density) {
                doping = `${layer.doping_type}: ${layer.doping_density.toExponential(2)} cm⁻³`;
            }

            let notes = layer.note || '-';
            if (layer.deep_donor_concentration || layer.deep_acceptor_concentration) {
                notes += ' <span class="badge badge-warning">Deep Levels</span>';
            }

            html += `
            <tr>
                <td>${idx + 1}</td>
                <td>${layer.material}</td>
                <td>${layer.thickness}</td>
                <td>${composition}</td>
                <td>${doping}</td>
                <td>${notes}</td>
            </tr>
`;
        });
        html += `
        </tbody>
    </table>
`;
    }

    if (includeBoundaryConditions) {
        html += `
    <h2>Boundary Conditions</h2>
    <table>
        <tr>
            <th>Boundary</th>
            <th>Type</th>
            <th>Parameters</th>
        </tr>
        <tr>
            <td>Surface</td>
            <td>${currentStructure.surface_params.type || 'slope'}</td>
            <td>${formatBoundaryParams(currentStructure.surface_params)}</td>
        </tr>
        <tr>
            <td>Substrate</td>
            <td>${currentStructure.substrate_params.type || 'slope'}</td>
            <td>${formatBoundaryParams(currentStructure.substrate_params)}</td>
        </tr>
    </table>
`;
    }

    if (includeValidation) {
        // Call validation (you'll need to implement this endpoint)
        html += `
    <h2>Validation</h2>
    <div class="warning-box">
        <strong>Note:</strong> Validation warnings will be implemented in backend API.
    </div>
`;
    }

    if (includeInputFile) {
        html += `
    <h2>Generated Input File</h2>
    <pre>${escapeHtml(getInputFilePreview())}</pre>
`;
    }

    html += `
</body>
</html>
`;

    return html;
}

// Generate Markdown report
function generateMarkdownReport(includeLayerTable, includeBoundaryConditions, includeInputFile, includeValidation) {
    let md = `# ${currentStructure.name}\n\n`;
    md += `**Generated:** ${new Date().toLocaleString()}\n\n`;
    md += `**Total Thickness:** ${currentStructure.layers.reduce((sum, l) => sum + l.thickness, 0).toFixed(2)} nm  \n`;
    md += `**Number of Layers:** ${currentStructure.layers.length}\n\n`;

    if (includeLayerTable) {
        md += `## Layer Structure\n\n`;
        md += `| # | Material | Thickness (nm) | Composition | Doping | Notes |\n`;
        md += `|---|----------|----------------|-------------|--------|-------|\n`;

        currentStructure.layers.forEach((layer, idx) => {
            let composition = '-';
            if (layer.composition_grading) {
                composition = `x=${layer.composition_grading.start}→${layer.composition_grading.stop}`;
            } else if (layer.composition !== null) {
                composition = `x=${layer.composition}`;
            }

            let doping = '-';
            if (layer.doping_type && layer.doping_density) {
                doping = `${layer.doping_type}: ${layer.doping_density.toExponential(2)}`;
            }

            let notes = layer.note || '-';

            md += `| ${idx + 1} | ${layer.material} | ${layer.thickness} | ${composition} | ${doping} | ${notes} |\n`;
        });
        md += `\n`;
    }

    if (includeBoundaryConditions) {
        md += `## Boundary Conditions\n\n`;
        md += `- **Surface:** ${currentStructure.surface_params.type || 'slope'} - ${formatBoundaryParams(currentStructure.surface_params)}\n`;
        md += `- **Substrate:** ${currentStructure.substrate_params.type || 'slope'} - ${formatBoundaryParams(currentStructure.substrate_params)}\n\n`;
    }

    if (includeInputFile) {
        md += `## Generated Input File\n\n`;
        md += `\`\`\`\n${getInputFilePreview()}\n\`\`\`\n\n`;
    }

    return md;
}

// Generate plain text report
function generateTextReport(includeLayerTable, includeBoundaryConditions, includeInputFile, includeValidation) {
    let txt = `${currentStructure.name}\n`;
    txt += `${'='.repeat(currentStructure.name.length)}\n\n`;
    txt += `Generated: ${new Date().toLocaleString()}\n`;
    txt += `Total Thickness: ${currentStructure.layers.reduce((sum, l) => sum + l.thickness, 0).toFixed(2)} nm\n`;
    txt += `Number of Layers: ${currentStructure.layers.length}\n\n`;

    if (includeLayerTable) {
        txt += `LAYER STRUCTURE\n`;
        txt += `${'-'.repeat(80)}\n\n`;

        currentStructure.layers.forEach((layer, idx) => {
            txt += `Layer ${idx + 1}: ${layer.material}\n`;
            txt += `  Thickness: ${layer.thickness} nm\n`;

            if (layer.composition_grading) {
                txt += `  Composition: x=${layer.composition_grading.start}→${layer.composition_grading.stop} (graded)\n`;
            } else if (layer.composition !== null) {
                txt += `  Composition: x=${layer.composition}\n`;
            }

            if (layer.doping_type && layer.doping_density) {
                txt += `  Doping: ${layer.doping_type}-type, ${layer.doping_density.toExponential(2)} cm⁻³\n`;
            }

            if (layer.note) {
                txt += `  Note: ${layer.note}\n`;
            }
            txt += `\n`;
        });
    }

    if (includeBoundaryConditions) {
        txt += `BOUNDARY CONDITIONS\n`;
        txt += `${'-'.repeat(80)}\n\n`;
        txt += `Surface: ${currentStructure.surface_params.type || 'slope'}\n`;
        txt += `  ${formatBoundaryParams(currentStructure.surface_params)}\n\n`;
        txt += `Substrate: ${currentStructure.substrate_params.type || 'slope'}\n`;
        txt += `  ${formatBoundaryParams(currentStructure.substrate_params)}\n\n`;
    }

    if (includeInputFile) {
        txt += `GENERATED INPUT FILE\n`;
        txt += `${'-'.repeat(80)}\n\n`;
        txt += getInputFilePreview() + '\n';
    }

    return txt;
}

// =============================================================================
// Ion Implants
// =============================================================================

// Initialize implants array on currentStructure if not present
function ensureImplantsArray() {
    if (!currentStructure.implants) {
        currentStructure.implants = [];
    }
}

function addImplantEntry(data) {
    ensureImplantsArray();

    if (currentStructure.implants.length >= 10) {
        showToast('Maximum of 10 implants allowed.', 'warning');
        return;
    }

    const implant = data || {
        implant_type: 'donor',
        dose: 1e12,
        projected_range: 500,
        straggle: 200
    };

    currentStructure.implants.push(implant);
    renderImplantList();
}

function removeImplant(index) {
    ensureImplantsArray();
    currentStructure.implants.splice(index, 1);
    renderImplantList();
}

function updateImplant(index, field, value) {
    ensureImplantsArray();
    if (index >= 0 && index < currentStructure.implants.length) {
        if (field === 'implant_type') {
            currentStructure.implants[index][field] = value;
        } else {
            currentStructure.implants[index][field] = parseFloat(value) || 0;
        }
    }
}

function renderImplantList() {
    ensureImplantsArray();
    const $list = $('#implantList');
    $list.empty();

    if (currentStructure.implants.length === 0) {
        $('#noImplantsMsg').show();
        return;
    }

    $('#noImplantsMsg').hide();

    currentStructure.implants.forEach((imp, idx) => {
        const html = `
            <div class="card card-body p-2 mb-2 bg-light">
                <div class="row g-2 align-items-center">
                    <div class="col-md-2">
                        <select class="form-select form-select-sm"
                                onchange="updateImplant(${idx}, 'implant_type', this.value)">
                            <option value="donor" ${imp.implant_type === 'donor' ? 'selected' : ''}>Donor</option>
                            <option value="acceptor" ${imp.implant_type === 'acceptor' ? 'selected' : ''}>Acceptor</option>
                        </select>
                        <small class="form-text text-muted">Type</small>
                    </div>
                    <div class="col-md-3">
                        <input type="number" class="form-control form-control-sm"
                               value="${imp.dose}" step="1e10"
                               onchange="updateImplant(${idx}, 'dose', this.value)">
                        <small class="form-text text-muted">Dose (cm⁻²)</small>
                    </div>
                    <div class="col-md-3">
                        <input type="number" class="form-control form-control-sm"
                               value="${imp.projected_range}" step="10"
                               onchange="updateImplant(${idx}, 'projected_range', this.value)">
                        <small class="form-text text-muted">Rp (Å)</small>
                    </div>
                    <div class="col-md-3">
                        <input type="number" class="form-control form-control-sm"
                               value="${imp.straggle}" step="10"
                               onchange="updateImplant(${idx}, 'straggle', this.value)">
                        <small class="form-text text-muted">ΔRp (Å)</small>
                    </div>
                    <div class="col-md-1 text-end">
                        <button type="button" class="btn btn-outline-danger btn-sm"
                                onclick="removeImplant(${idx})" title="Remove implant">
                            <i class="bi bi-trash"></i>
                        </button>
                    </div>
                </div>
            </div>
        `;
        $list.append(html);
    });
}

// Helper functions
function formatBoundaryParams(params) {
    if (!params || !params.type) return '-';

    let str = '';
    if (params.type === 'schottky') {
        str = `Barrier height: ${params.barrier_height || 0.6} eV`;
    } else if (params.type === 'ohmic') {
        str = 'Ohmic contact';
    } else {
        str = 'Slope = 0';
    }

    if (params.voltage_source) {
        str += `, Voltage source: ${params.voltage_source} = ${params.voltage_value || 0} V`;
    }

    return str;
}

function updateCompositionFieldState($materialSelect, compositionInputId, compositionStartId, compositionStopId, enableGradingId) {
    // Check if selected material is ternary (has data-ternary="true" attribute)
    const selectedOption = $materialSelect.find('option:selected');
    const isTernary = selectedOption.data('ternary') === true;

    if (isTernary) {
        // Enable composition fields for ternary materials
        if (compositionInputId) $(compositionInputId).prop('disabled', false).closest('.mb-3').show();
        if (compositionStartId) $(compositionStartId).prop('disabled', false);
        if (compositionStopId) $(compositionStopId).prop('disabled', false);
        if (enableGradingId) $(enableGradingId).prop('disabled', false).closest('.form-check').parent().show();
    } else {
        // Disable and hide composition fields for binary materials
        if (compositionInputId) {
            $(compositionInputId).prop('disabled', true).val('').closest('.mb-3').hide();
        }
        if (compositionStartId) $(compositionStartId).prop('disabled', true).val('');
        if (compositionStopId) $(compositionStopId).prop('disabled', true).val('');
        if (enableGradingId) {
            $(enableGradingId).prop('disabled', true).prop('checked', false).closest('.form-check').parent().hide();
            // Show single composition div by default when grading is disabled
            if (compositionInputId) {
                $('#singleCompositionDiv').show();
                $('#gradedCompositionDiv').hide();
            }
        }
    }
}

function updateDopingDensityFieldState($dopingTypeSelect, densityDivId) {
    // Show doping density field only when n-type or p-type is selected (not undoped)
    const dopingType = $dopingTypeSelect.val();

    if (dopingType === 'n' || dopingType === 'p') {
        // Show the doping density field
        $(densityDivId).show();
    } else {
        // Hide and clear the doping density field for undoped
        $(densityDivId).hide();
        $(densityDivId).find('input').val('');
    }
}

function getInputFilePreview() {
    // Generate a preview of the input file
    // This is a simplified version - you might want to call the backend API
    let preview = `# ${currentStructure.name}\n\n`;
    preview += `surface\t${currentStructure.surface_params.type || 'slope=0'}\n\n`;

    currentStructure.layers.forEach(layer => {
        preview += `${layer.material}\tt=${layer.thickness * 10}`;
        if (layer.composition !== null) {
            preview += `\tx=${layer.composition}`;
        }
        preview += '\n';
    });

    preview += `\nsubstrate\t${currentStructure.substrate_params.type || 'slope=0'}\n`;
    preview += `\nfullyionized\ntemp=300K\ndy=50\n`;

    return preview;
}

function escapeHtml(text) {
    const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    return text.replace(/[&<>"']/g, m => map[m]);
}

// Safely hide modal by removing focus first to prevent ARIA warnings
function safeHideModal(modalSelector) {
    const $modal = $(modalSelector);

    // Remove focus from any element inside the modal
    $modal.find(':focus').blur();

    // Hide the modal
    const modalInstance = bootstrap.Modal.getInstance($modal[0]);
    if (modalInstance) {
        modalInstance.hide();
    }
}

// =============================================================================
// Batch Processing Functions
// =============================================================================

/**
 * Show the batch run modal
 */
function showBatchRunModal() {
    const modal = new bootstrap.Modal(document.getElementById('batchRunModal'));
    modal.show();

    // Reset progress section
    $('#batchProgressSection').hide();
    $('#batchResultsList').empty();
    $('#batchStatusMessage').empty();
    $('#batchProgressBar').css('width', '0%').text('0%');

    // Load model list
    loadBatchModelList();
}

/**
 * Load available models for batch processing
 */
function loadBatchModelList() {
    $('#batchModelList').html(`
        <div class="text-center p-4 text-muted">
            <div class="spinner-border spinner-border-sm me-2" role="status"></div>
            Loading models...
        </div>
    `);

    $.ajax({
        url: '/api/structure/list',
        method: 'GET',
        success: function(response) {
            if (response.success) {
                displayBatchModelList(response.structures);
            } else {
                showToast('Error loading models: ' + response.error, 'error');
                $('#batchModelList').html(`
                    <div class="alert alert-danger">
                        <i class="bi bi-exclamation-triangle"></i> Failed to load models
                    </div>
                `);
            }
        },
        error: function(xhr) {
            showToast('Error loading models', 'error');
            $('#batchModelList').html(`
                <div class="alert alert-danger">
                    <i class="bi bi-exclamation-triangle"></i> Failed to load models
                </div>
            `);
        }
    });
}

/**
 * Display model list with checkboxes
 */
function displayBatchModelList(structures) {
    const $list = $('#batchModelList');
    $list.empty();

    if (structures.length === 0) {
        $list.html(`
            <div class="alert alert-info">
                <i class="bi bi-info-circle"></i> No models found. Save some structures first.
            </div>
        `);
        return;
    }

    structures.forEach((structure, index) => {
        const hasSettings = structure.has_simulation_settings;
        const statusIcon = hasSettings
            ? '<i class="bi bi-check-circle-fill text-success"></i>'
            : '<i class="bi bi-exclamation-triangle-fill text-warning"></i>';

        const statusText = hasSettings
            ? 'Has simulation settings'
            : 'Missing settings (will use defaults)';

        const timestamp = new Date(structure.timestamp * 1000).toLocaleString();

        const item = $(`
            <div class="list-group-item">
                <div class="d-flex justify-content-between align-items-start">
                    <div class="form-check flex-grow-1">
                        <input class="form-check-input model-checkbox" type="checkbox"
                               id="model_${index}" data-filename="${structure.filename}">
                        <label class="form-check-label w-100"
                               for="model_${index}">
                            <div class="fw-bold">${structure.name}</div>
                            <small class="text-muted">
                                ${structure.layer_count} layers | ${timestamp}
                            </small>
                            <div class="mt-1">
                                <small class="text-muted">
                                    ${statusIcon} ${statusText}
                                </small>
                                <span class="settings-preview ms-2" data-index="${index}">
                                    <span class="spinner-border spinner-border-sm" role="status"></span>
                                </span>
                            </div>
                        </label>
                    </div>
                    <button class="btn btn-sm btn-outline-primary edit-model-settings-btn ms-2"
                            data-filename="${structure.filename}"
                            data-name="${structure.name}"
                            title="Edit Settings">
                        <i class="bi bi-gear"></i>
                    </button>
                </div>
            </div>
        `);

        $list.append(item);

        // Load settings preview asynchronously
        if (hasSettings) {
            loadSettingsPreview(structure.filename, index);
        } else {
            $(`.settings-preview[data-index="${index}"]`).html(
                '<span class="badge bg-secondary">Default: 300K | P</span>'
            );
        }
    });

    updateSelectedModelCount();
}

/**
 * Load and display settings preview for a model
 */
function loadSettingsPreview(filename, index) {
    $.ajax({
        url: `/api/structure/load/${filename}`,
        method: 'GET',
        success: function(response) {
            if (response.success && response.structure.simulation_settings) {
                const settings = response.structure.simulation_settings;
                const temp = settings.temperature || 300;
                const mode = settings.mode === 'schrodinger_poisson' ? 'S-P' : 'P';
                const sweep = settings.voltage_sweep && settings.voltage_sweep.enabled ? 'Sweep' : 'Single';
                const cv = settings.cv_mode ? 'CV' : '';

                let preview = `${temp}K | ${mode} | ${sweep}`;
                if (cv) preview += ` | ${cv}`;

                $(`.settings-preview[data-index="${index}"]`).html(
                    `<span class="badge bg-info">${preview}</span>`
                );
            } else {
                $(`.settings-preview[data-index="${index}"]`).html('');
            }
        },
        error: function() {
            $(`.settings-preview[data-index="${index}"]`).html('');
        }
    });
}

/**
 * Toggle all model checkboxes
 */
function toggleAllCheckboxes() {
    const checked = $('#selectAllModels').is(':checked');
    $('.model-checkbox').prop('checked', checked);
    updateSelectedModelCount();
}

/**
 * Update selected model count badge
 */
function updateSelectedModelCount() {
    const count = $('.model-checkbox:checked').length;
    $('#selectedCountBadge').text(`${count} selected`);
}

/**
 * Start batch simulation
 */
function startBatchSimulation() {
    const selectedModels = [];
    $('.model-checkbox:checked').each(function() {
        selectedModels.push({
            filename: $(this).data('filename')
        });
    });

    if (selectedModels.length === 0) {
        showToast('Please select at least one model', 'warning');
        return;
    }

    const continueOnError = $('#continueOnError').is(':checked');

    // Disable controls
    $('#startBatchBtn').prop('disabled', true);
    $('#refreshModelListBtn').prop('disabled', true);
    $('.model-checkbox, #selectAllModels, #continueOnError').prop('disabled', true);

    // Show progress section
    $('#batchProgressSection').show();
    $('#batchStatusMessage').html(`
        <div class="alert alert-info">
            <i class="bi bi-hourglass-split"></i> Starting batch simulation...
        </div>
    `);

    // Start batch run
    $.ajax({
        url: '/api/simulation/batch-run',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            models: selectedModels,
            continue_on_error: continueOnError
        }),
        success: function(response) {
            if (response.success) {
                showToast('Batch simulation started', 'success');
                monitorBatchProgress(response.batch_id);
            } else {
                showToast('Error starting batch: ' + response.error, 'error');
                resetBatchControls();
            }
        },
        error: function(xhr) {
            showToast('Error starting batch simulation', 'error');
            resetBatchControls();
        }
    });
}

/**
 * Monitor batch progress via SSE
 */
function monitorBatchProgress(batchId) {
    const eventSource = new EventSource(`/api/simulation/monitor/${batchId}`);

    eventSource.onmessage = function(event) {
        const data = JSON.parse(event.data);

        if (data.type === 'progress') {
            // Update progress bar
            const percent = Math.round((data.current / data.total) * 100);
            $('#batchProgressBar').css('width', `${percent}%`).text(`${percent}%`);

            // Update status message
            $('#batchStatusMessage').html(`
                <div class="alert alert-info">
                    <i class="bi bi-hourglass-split"></i> ${data.message}
                </div>
            `);
        } else if (data.type === 'result') {
            // Add result to list
            const resultData = {
                filename: data.filename,
                model_name: data.model_name,
                status: data.result_status,
                output_folder: data.output_folder,
                error: data.error
            };
            displayBatchResult(resultData);
        } else if (data.type === 'complete') {
            // Batch complete
            $('#batchProgressBar').removeClass('progress-bar-animated progress-bar-striped')
                                  .addClass('bg-success');
            $('#batchStatusMessage').html(`
                <div class="alert alert-success">
                    <i class="bi bi-check-circle"></i> ${data.message}
                    <br><small>Redirecting to results page...</small>
                </div>
            `);
            eventSource.close();
            resetBatchControls();

            // Redirect to results page after brief delay to show success message
            setTimeout(function() {
                window.location.href = '/results';
            }, 2000);
        } else if (data.type === 'error' || data.status === 'failed') {
            // Error occurred
            $('#batchStatusMessage').html(`
                <div class="alert alert-danger">
                    <i class="bi bi-exclamation-triangle"></i> Error: ${data.message}
                </div>
            `);
            eventSource.close();
            resetBatchControls();
        } else if (data.status === 'stopped') {
            // Batch stopped
            $('#batchProgressBar').removeClass('progress-bar-animated progress-bar-striped')
                                  .addClass('bg-warning');
            $('#batchStatusMessage').html(`
                <div class="alert alert-warning">
                    <i class="bi bi-exclamation-triangle"></i> ${data.message}
                </div>
            `);
            eventSource.close();
            resetBatchControls();
        }
    };

    eventSource.onerror = function() {
        showToast('Connection to server lost', 'error');
        eventSource.close();
        resetBatchControls();
    };
}

/**
 * Display individual batch result
 */
function displayBatchResult(result) {
    const $resultsList = $('#batchResultsList');

    let resultHtml;
    if (result.status === 'success') {
        resultHtml = `
            <div class="list-group-item list-group-item-success">
                <div class="d-flex justify-content-between align-items-start">
                    <div>
                        <i class="bi bi-check-circle-fill"></i>
                        <strong>${result.model_name || result.filename}</strong>
                        <div class="small text-muted">Output: ${result.output_folder}</div>
                    </div>
                    <span class="badge bg-success">Success</span>
                </div>
            </div>
        `;
    } else {
        resultHtml = `
            <div class="list-group-item list-group-item-danger">
                <div class="d-flex justify-content-between align-items-start">
                    <div>
                        <i class="bi bi-x-circle-fill"></i>
                        <strong>${result.model_name || result.filename}</strong>
                        <div class="small text-danger">${result.error}</div>
                    </div>
                    <span class="badge bg-danger">Failed</span>
                </div>
            </div>
        `;
    }

    $resultsList.append(resultHtml);
}

/**
 * Reset batch controls after completion
 */
function resetBatchControls() {
    $('#startBatchBtn').prop('disabled', false);
    $('#refreshModelListBtn').prop('disabled', false);
    $('.model-checkbox, #selectAllModels, #continueOnError').prop('disabled', false);
}

// =============================================================================
// Save Settings
// =============================================================================

/**
 * Variable to track the model being edited in batch mode
 */
let batchEditingModel = null;
let batchSelectedModels = [];  // Store selected model checkboxes when editing

/**
 * Save simulation settings to the current structure without running simulation
 */
function saveSimulationSettings() {
    if (!currentStructure || !currentStructure.name) {
        alert('Please load or create a structure first.');
        return;
    }

    // Capture current simulation settings
    const simSettings = {
        temperature: parseFloat($('#simTemperature').val()) || 300.0,
        temp_unit: $('#tempUnit').val() || 'K',
        mode: $('#simMode').val() || 'poisson',
        mesh_spacing: parseFloat($('#meshSpacing').val()) || 75.0,
        voltage_sweep: {
            enabled: $('#enableBiasSweep').is(':checked'),
            source: $('#sweepVoltageSource').val() || 'v1',
            start: parseFloat($('#sweepStart').val()) || 0.0,
            stop: parseFloat($('#sweepStop').val()) || -2.0,
            step: parseFloat($('#sweepStep').val()) || -0.5
        },
        cv_mode: $('#enableCV').is(':checked') ? ($('#cvMode').val() || 'cv') : null,
        schrodinger_params: {
            start: parseFloat($('#schrodingerStart').val()) || 20,
            stop: $('#schrodingerStop').val() ? parseFloat($('#schrodingerStop').val()) : null
        },
        convergence: {
            criteria: $('#enableAdvConvergence').is(':checked') ?
                     (parseFloat($('#convergenceCriteria').val()) || 1e-5) : null,
            cv_criteria: $('#enableAdvConvergence').is(':checked') ?
                        (parseFloat($('#cvConvergenceCriteria').val()) || 1e-10) : null,
            max_iterations: $('#enableAdvConvergence').is(':checked') ?
                           (parseInt($('#maxIterations').val()) || 100) : null,
            will_robinson: $('#enableAdvConvergence').is(':checked') ?
                          ($('#willRobinson').val() || null) : null
        }
    };

    // Update structure with new settings
    currentStructure.simulation_settings = simSettings;

    // Log what mode is being saved for debugging
    console.log('Saving simulation settings with mode:', simSettings.mode);

    // Prepare data with optional filename to update existing file
    const saveData = { ...currentStructure };

    // Use batch editing filename if available, otherwise use current filename
    if (batchEditingModel && batchEditingModel.filename) {
        saveData.filename = batchEditingModel.filename;
    } else if (currentFilename) {
        saveData.filename = currentFilename;
    }

    // Save to file
    const $btn = $('#saveSettingsBtn');
    const originalHtml = $btn.html();
    $btn.prop('disabled', true);
    $btn.html('<span class="spinner-border spinner-border-sm me-2"></span>Saving...');

    $.ajax({
        url: '/api/structure/save',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify(saveData),
        success: function(response) {
            if (response.success) {
                // Update current filename if it was newly generated
                if (!currentFilename && !batchEditingModel && response.filename) {
                    currentFilename = response.filename;
                }

                const modeText = simSettings.mode === 'schrodinger_poisson' ? 'Schrödinger-Poisson' : 'Poisson Only';
                showToast(`Settings saved successfully! Mode: ${modeText}`, 'success');

                // If we were editing a batch model, return to batch runner
                if (batchEditingModel) {
                    // Close settings modal
                    const settingsModal = bootstrap.Modal.getInstance($('#simSettingsModal')[0]);
                    if (settingsModal) {
                        settingsModal.hide();
                    }

                    // Small delay to ensure settings modal is fully closed before opening batch modal
                    setTimeout(function() {
                        // Refresh the batch list to show updated settings
                        loadBatchModelList();

                        // Re-open the batch runner modal
                        const batchModal = new bootstrap.Modal($('#batchRunModal')[0]);
                        batchModal.show();

                        // Restore selections after the list is loaded
                        setTimeout(function() {
                            batchSelectedModels.forEach(function(filename) {
                                $(`.model-checkbox[data-filename="${filename}"]`).prop('checked', true);
                            });
                            updateSelectedModelCount();
                        }, 100);

                        batchEditingModel = null;
                        batchSelectedModels = [];
                    }, 200);
                }
            } else {
                alert('Error saving settings: ' + response.error);
            }
            $btn.prop('disabled', false);
            $btn.html(originalHtml);
        },
        error: function(xhr) {
            alert('Error saving settings: ' + (xhr.responseJSON?.error || 'Unknown error'));
            $btn.prop('disabled', false);
            $btn.html(originalHtml);
        }
    });
}

/**
 * Edit settings for a model in batch mode
 */
function editModelSettings(filename, modelName) {
    // Save currently selected models
    batchSelectedModels = [];
    $('.model-checkbox:checked').each(function() {
        batchSelectedModels.push($(this).data('filename'));
    });

    // Close the batch runner modal
    const batchModal = bootstrap.Modal.getInstance($('#batchRunModal')[0]);
    if (batchModal) {
        batchModal.hide();
    }

    // Load the model first
    $.ajax({
        url: '/api/structure/load',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({ filename: filename }),
        success: function(response) {
            if (response.success) {
                // Store the loaded structure
                const tempStructure = currentStructure;
                currentStructure = response.structure;
                batchEditingModel = { filename: filename, name: modelName };

                // Load settings into the simulation settings form
                if (currentStructure.simulation_settings) {
                    const settings = currentStructure.simulation_settings;

                    // Use proper null/undefined checks to handle 0 and negative values correctly
                    $('#simTemperature').val(settings.temperature !== undefined ? settings.temperature : 300.0);
                    $('#tempUnit').val(settings.temp_unit || 'K');
                    $('#simMode').val(settings.mode || 'poisson');
                    $('#meshSpacing').val(settings.mesh_spacing !== undefined ? settings.mesh_spacing : 75.0);

                    // Show/hide Schrödinger params based on loaded mode
                    if (settings.mode === 'schrodinger_poisson') {
                        $('#schrodingerParams').show();
                    } else {
                        $('#schrodingerParams').hide();
                    }

                    if (settings.voltage_sweep) {
                        $('#enableBiasSweep').prop('checked', !!settings.voltage_sweep.enabled);
                        $('#sweepVoltageSource').val(settings.voltage_sweep.source || 'v1');
                        $('#sweepStart').val(settings.voltage_sweep.start !== undefined ? settings.voltage_sweep.start : 0.0);
                        $('#sweepStop').val(settings.voltage_sweep.stop !== undefined ? settings.voltage_sweep.stop : -2.0);
                        $('#sweepStep').val(settings.voltage_sweep.step !== undefined ? settings.voltage_sweep.step : -0.5);

                        // Toggle visibility
                        if (settings.voltage_sweep.enabled) {
                            $('#biasSweepParams').show();
                        } else {
                            $('#biasSweepParams').hide();
                        }
                    } else {
                        // Reset voltage sweep if not present
                        $('#enableBiasSweep').prop('checked', false);
                        $('#biasSweepParams').hide();
                    }

                    if (settings.cv_mode) {
                        $('#enableCV').prop('checked', true);
                        $('#cvMode').val(settings.cv_mode);
                        $('#cvParams').show();
                    } else {
                        $('#enableCV').prop('checked', false);
                        $('#cvParams').hide();
                    }

                    // Schrödinger parameters
                    if (settings.schrodinger_params) {
                        $('#schrodingerStart').val(settings.schrodinger_params.start !== undefined ? settings.schrodinger_params.start : 20);
                        if (settings.schrodinger_params.stop !== undefined && settings.schrodinger_params.stop !== null) {
                            $('#schrodingerStop').val(settings.schrodinger_params.stop);
                        } else {
                            $('#schrodingerStop').val('');
                        }
                    } else {
                        $('#schrodingerStart').val(20);
                        $('#schrodingerStop').val('');
                    }

                    // Convergence parameters
                    if (settings.convergence) {
                        const hasConvergenceSettings =
                            (settings.convergence.criteria !== null && settings.convergence.criteria !== undefined) ||
                            (settings.convergence.cv_criteria !== null && settings.convergence.cv_criteria !== undefined) ||
                            (settings.convergence.max_iterations !== null && settings.convergence.max_iterations !== undefined) ||
                            settings.convergence.will_robinson;

                        if (hasConvergenceSettings) {
                            $('#enableAdvConvergence').prop('checked', true);
                            $('#advConvergenceParams').show();

                            if (settings.convergence.criteria !== undefined && settings.convergence.criteria !== null)
                                $('#convergenceCriteria').val(settings.convergence.criteria);
                            if (settings.convergence.cv_criteria !== undefined && settings.convergence.cv_criteria !== null)
                                $('#cvConvergenceCriteria').val(settings.convergence.cv_criteria);
                            if (settings.convergence.max_iterations !== undefined && settings.convergence.max_iterations !== null)
                                $('#maxIterations').val(settings.convergence.max_iterations);
                            if (settings.convergence.will_robinson)
                                $('#willRobinson').val(settings.convergence.will_robinson);
                        } else {
                            $('#enableAdvConvergence').prop('checked', false);
                            $('#advConvergenceParams').hide();
                        }
                    } else {
                        $('#enableAdvConvergence').prop('checked', false);
                        $('#advConvergenceParams').hide();
                    }
                } else {
                    // Set defaults when no simulation settings exist
                    $('#simTemperature').val(300.0);
                    $('#tempUnit').val('K');
                    $('#simMode').val('poisson');
                    $('#meshSpacing').val(75.0);
                    $('#schrodingerParams').hide();  // Hide Schrödinger params for Poisson-only default
                    $('#enableBiasSweep').prop('checked', false);
                    $('#biasSweepParams').hide();
                    $('#enableCV').prop('checked', false);
                    $('#cvParams').hide();
                    $('#schrodingerStart').val(20);
                    $('#schrodingerStop').val('');
                    $('#enableAdvConvergence').prop('checked', false);
                    $('#advConvergenceParams').hide();
                }

                // Show modal with indicator that we're editing a batch model
                $('#simSettingsModal .modal-title').html(
                    `<i class="bi bi-gear"></i> Edit Settings: ${modelName}`
                );
                const modal = new bootstrap.Modal($('#simSettingsModal')[0]);
                modal.show();

                showToast(`Editing settings for: ${modelName}`, 'info');
            } else {
                alert('Error loading model: ' + response.error);
            }
        },
        error: function(xhr) {
            alert('Error loading model: ' + (xhr.responseJSON?.error || 'Unknown error'));
        }
    });
}

// =============================================================================
// Event Bindings - Batch Processing
// =============================================================================

$(document).ready(function() {
    // Batch run button
    $('#batchRunBtn').click(showBatchRunModal);

    // Refresh model list
    $('#refreshModelListBtn').click(loadBatchModelList);

    // Select all checkbox
    $('#selectAllModels').change(toggleAllCheckboxes);

    // Individual checkbox change
    $(document).on('change', '.model-checkbox', updateSelectedModelCount);

    // Start batch button
    $('#startBatchBtn').click(startBatchSimulation);

    // Save settings button
    $('#saveSettingsBtn').click(saveSimulationSettings);

    // Edit model settings button (delegated event for dynamically created buttons)
    $(document).on('click', '.edit-model-settings-btn', function() {
        const filename = $(this).data('filename');
        const name = $(this).data('name');
        editModelSettings(filename, name);
    });

    // Reset modal title when opening simulation settings normally
    $('#runSimBtn').click(function() {
        $('#simSettingsModal .modal-title').html('<i class="bi bi-gear"></i> Simulation Settings');
        batchEditingModel = null;
    });

    // Reset batch editing mode when modal is closed
    $('#simSettingsModal').on('hidden.bs.modal', function() {
        if (batchEditingModel) {
            // If closed without saving, restore batch runner
            setTimeout(function() {
                // Re-open the batch runner modal
                const batchModal = new bootstrap.Modal($('#batchRunModal')[0]);
                batchModal.show();

                // Restore selections after a brief delay
                setTimeout(function() {
                    batchSelectedModels.forEach(function(filename) {
                        $(`.model-checkbox[data-filename="${filename}"]`).prop('checked', true);
                    });
                    updateSelectedModelCount();
                    batchSelectedModels = [];
                }, 100);
            }, 200);

            batchEditingModel = null;
            $('#simSettingsModal .modal-title').html('<i class="bi bi-gear"></i> Simulation Settings');
        }
    });
});