export function defineRegistry(options) {
  const {
    hostName,
    dirSegment,
    schemaModules,
    configModules,
    runtimeModules,
    validateModule,
    deriveEntryExtras
  } = options;
  const pathRe = new RegExp(`/${dirSegment}/([^/]+)/([^/]+)/schema\\.(?:ts|js)$`);
  const parsePath = (path) => {
    const match = pathRe.exec(path);
    if (!match) throw new Error(`[${hostName}] unrecognized schema path: ${path}`);
    return { date: match[1], type: match[2] };
  };
  const findSibling = (map, date, type, file) => {
    const suffix = `/${dirSegment}/${date}/${type}/${file}`;
    for (const [key, value] of Object.entries(map)) {
      if (key.endsWith(suffix)) return value;
    }
    throw new Error(`[${hostName}] missing ${file} for ${type}@${date}`);
  };
  let cached = null;
  const compute = () => {
    if (cached) return cached;
    const drafts = [];
    for (const [path, mod] of Object.entries(schemaModules)) {
      const { date, type } = parsePath(path);
      if (mod.type !== type) {
        throw new Error(`[${hostName}] type "${mod.type}" does not match folder "${type}"`);
      }
      if (mod.compatibilityDate !== date) {
        throw new Error(`[${hostName}] compatibilityDate "${mod.compatibilityDate}" does not match folder "${date}"`);
      }
      validateModule?.(mod, type, date);
      drafts.push({
        type: mod.type,
        compatibilityDate: mod.compatibilityDate,
        config: findSibling(configModules, date, type, "config.vue"),
        runtime: findSibling(runtimeModules, date, type, "runtime.vue"),
        module: mod
      });
    }
    const mapExtras = deriveEntryExtras ? deriveEntryExtras(drafts) : () => ({});
    cached = drafts.map((draft) => ({
      type: draft.type,
      compatibilityDate: draft.compatibilityDate,
      config: draft.config,
      runtime: draft.runtime,
      module: draft.module,
      ...mapExtras(draft)
    }));
    return cached;
  };
  const find = (type, compatibilityDate) => compute().find((e) => e.type === type && e.compatibilityDate === compatibilityDate);
  return {
    get ENTRIES() {
      return compute();
    },
    find
  };
}
