/**
 * Custom ESM loader to fix missing .js extensions in @excalidraw/excalidraw deps.
 *
 * Problems patched:
 * 1. excalidraw imports 'roughjs/bin/rough' (and other roughjs/* paths) without .js
 * 2. roughjs/* files import sibling modules as './canvas' (relative, no .js)
 * 3. JSON files need { type: 'json' } import attribute in Node.js v22+
 *
 * Usage: node --loader ./loader.mjs server.mjs [args...]
 */

import { fileURLToPath, pathToFileURL } from 'url';
import { dirname, resolve as pathResolve } from 'path';

const __dirname = dirname(fileURLToPath(import.meta.url));

// Modules that have incompatible ESM format — redirect to local stubs
const STUBS = {
  '@excalidraw/laser-pointer': pathToFileURL(pathResolve(__dirname, 'stubs/laser-pointer.mjs')).href,
};

export async function resolve(specifier, context, nextResolve) {
  // 0. Module stubs (incompatible ESM format packages)
  if (STUBS[specifier]) {
    return { url: STUBS[specifier], shortCircuit: true };
  }

  // 1. Bare roughjs/* specifiers without .js extension
  if (/^roughjs\/bin\/[a-z-]+$/.test(specifier)) {
    return nextResolve(`${specifier}.js`, context);
  }

  // 2. Relative imports without extension (e.g. './canvas' from roughjs/bin/rough.js)
  //    These come in as relative paths that resolve to extensionless file URLs.
  if (specifier.startsWith('./') || specifier.startsWith('../')) {
    // Try resolving first; if it fails with a missing-extension error, add .js
    try {
      return await nextResolve(specifier, context);
    } catch (err) {
      if (err.code === 'ERR_MODULE_NOT_FOUND') {
        // Try appending .js
        try {
          return await nextResolve(`${specifier}.js`, context);
        } catch {
          // Fall through to original error
        }
      }
      throw err;
    }
  }

  // 3. JSON imports need type: 'json' attribute
  if (specifier.endsWith('.json')) {
    const resolved = await nextResolve(specifier, context);
    if (!resolved.importAttributes?.type) {
      return {
        ...resolved,
        importAttributes: { ...resolved.importAttributes, type: 'json' },
      };
    }
    return resolved;
  }

  return nextResolve(specifier, context);
}

export async function load(url, context, nextLoad) {
  // Ensure JSON files are loaded with json format
  if (url.endsWith('.json')) {
    return nextLoad(url, {
      ...context,
      importAttributes: { ...context.importAttributes, type: 'json' },
    });
  }
  return nextLoad(url, context);
}
