/**
 * Write a firmware file directly to a removable mass-storage drive
 * selected by the user (e.g. MICROBIT or RPI-RP2).
 */
export async function flashFileToDrive(onLog, onProgress, options = {}) {
  const { firmwareUrl, outputName = 'firmware.bin', driveHint = 'device drive' } = options;
  if (!firmwareUrl) throw new Error('No firmware URL provided');

  onLog?.('Fetching firmware...\n');
  const resp = await fetch(firmwareUrl);
  if (!resp.ok) throw new Error(`Firmware fetch failed: ${resp.status}`);
  const fileData = new Uint8Array(await resp.arrayBuffer());
  onLog?.(`Firmware: ${(fileData.length / 1024).toFixed(0)} KB\n\n`);

  onLog?.(`Select the ${driveHint} in the folder picker.\n\n`);

  let dirHandle;
  try {
    dirHandle = await window.showDirectoryPicker({ mode: 'readwrite' });
  } catch (err) {
    if (err?.name === 'AbortError') throw new Error('Cancelled - no folder selected');
    throw err;
  }

  onLog?.(`Writing ${outputName} to ${dirHandle.name}...\n`);
  const fileHandle = await dirHandle.getFileHandle(outputName, { create: true });
  const writable = await fileHandle.createWritable();

  const CHUNK_SIZE = 64 * 1024;
  let written = 0;
  try {
    while (written < fileData.length) {
      const end = Math.min(written + CHUNK_SIZE, fileData.length);
      await writable.write({
        type: 'write',
        position: written,
        data: fileData.slice(written, end),
      });
      written = end;
      onProgress?.(Math.round((written / fileData.length) * 95));
    }
    await writable.close();
  } catch (err) {
    // Some bootloaders unmount as soon as the file is fully written.
    if (written >= fileData.length) {
      onLog?.('(Drive disconnected - device is rebooting with new firmware)\n');
    } else {
      throw err;
    }
  }

  onProgress?.(100);
  onLog?.('Done!\n');
}

