def generate_download_settings_js(dl_fn, control_ids):
    js_code = """
    async (""" + ", ".join([f'{ctrl[0]}' for ctrl in control_ids]) + """) => {  
        const password = prompt("Please enter a password for encryption", " ");
        if (!password) {
            alert("No password provided. Cancelling download.");
            return;
        }
        
        let settings = {""" + ", ".join([f'"{ctrl[0]}": {ctrl[0]}' for ctrl in control_ids]) + """};
        const settingsStr = JSON.stringify(settings);
        const textEncoder = new TextEncoder();
        const encodedSettings = textEncoder.encode(settingsStr);
        const salt = crypto.getRandomValues(new Uint8Array(16));
        const passwordBuffer = textEncoder.encode(password);
        const keyMaterial = await crypto.subtle.importKey('raw', passwordBuffer, {name: 'PBKDF2'}, false, ['deriveKey']);
        const key = await crypto.subtle.deriveKey(
            {name: 'PBKDF2', salt: salt, iterations: 100000, hash: 'SHA-256'}, 
            keyMaterial, 
            {name: 'AES-GCM', length: 256}, 
            false, 
            ['encrypt']
        );
        const iv = crypto.getRandomValues(new Uint8Array(12));
        const encryptedSettings = await crypto.subtle.encrypt({name: 'AES-GCM', iv: iv}, key, encodedSettings);
        const blob = new Blob([salt, iv, new Uint8Array(encryptedSettings)], {type: 'application/octet-stream'});
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = '""" + dl_fn + """';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }"""
    return js_code

def generate_upload_settings_js(control_ids):
    js_code = """
    async () => {
        const input = document.createElement('input');
        input.type = 'file';
        input.onchange = async e => {
            const file = e.target.files[0];
            if (!file) {
                alert("No file selected.");
                return;
            }
            
            const password = prompt("Please enter the password for decryption", " ");
            if (!password) {
                alert("No password provided. Cancelling upload.");
                return;
            }
            
            const arrayBuffer = await file.arrayBuffer();
            const salt = arrayBuffer.slice(0, 16);
            const iv = arrayBuffer.slice(16, 28);
            const encryptedData = arrayBuffer.slice(28);
            const textEncoder = new TextEncoder();
            const passwordBuffer = textEncoder.encode(password);
            const keyMaterial = await crypto.subtle.importKey('raw', passwordBuffer, {name: 'PBKDF2'}, false, ['deriveKey']);
            const key = await crypto.subtle.deriveKey(
                {name: 'PBKDF2', salt: salt, iterations: 100000, hash: 'SHA-256'}, 
                keyMaterial, 
                {name: 'AES-GCM', length: 256}, 
                false, 
                ['decrypt']
            );
            
            try {
                const decryptedData = await crypto.subtle.decrypt({name: 'AES-GCM', iv: iv}, key, encryptedData);
                const textDecoder = new TextDecoder();
                const settingsStr = textDecoder.decode(decryptedData);
                const settings = JSON.parse(settingsStr);
                """ + "\n".join([f'document.querySelector("{ctrl[1]}").value = settings["{ctrl[0]}"];' for ctrl in control_ids]) + """
                """ + "\n".join([f'document.querySelector("{ctrl[1]}").dispatchEvent(new InputEvent("input", {{ bubbles: true }}));' for ctrl in control_ids]) + """
            } catch (err) {
                alert("Failed to decrypt. Check your password and try again.");
                console.error("Decryption failed:", err);
            }
        };
        input.click();
    }"""
    return js_code