export function createSetupOperationRegistry({ logRegistry = null, onChange = null } = {}) {
  const operations = [];
  const byId = new Map();
  let nextId = 1;

  function emitChange() {
    onChange?.(listOperations());
  }

  function start({
    config,
    stage,
    kind = "setup",
    summary = null,
    parentId = null,
    recordLog = true,
  }) {
    const startedAt = new Date().toISOString();
    const logRecord = recordLog ? logRegistry?.ensureSetupLogRecord(config, stage) || null : null;
    const operation = {
      id: `setup-${nextId++}`,
      serviceName: config.name,
      runtimeLabel: config.runtimeLabel || config.name,
      stage,
      kind,
      summary,
      parentId,
      status: "running",
      startedAt,
      finishedAt: null,
      durationMs: null,
      error: null,
      logRef: logRecord
        ? {
            path: logRecord.path,
            stage: logRecord.stage,
          }
        : null,
      _logRecord: logRecord,
    };
    operations.push(operation);
    byId.set(operation.id, operation);
    emitChange();
    return operation;
  }

  function finish(target, { status = "passed", summary, error = null } = {}) {
    const operation = typeof target === "string" ? byId.get(target) : target;
    if (!operation) return null;
    const finishedAt = new Date().toISOString();
    operation.finishedAt = finishedAt;
    operation.durationMs = Math.max(
      0,
      Date.parse(finishedAt) - Date.parse(operation.startedAt || finishedAt)
    );
    operation.status = status;
    if (summary !== undefined) operation.summary = summary;
    if (error !== null) operation.error = String(error);
    emitChange();
    return operation;
  }

  function recordCached({ config, stage, kind = "setup", summary = null, parentId = null }) {
    const now = new Date().toISOString();
    const operation = {
      id: `setup-${nextId++}`,
      serviceName: config.name,
      runtimeLabel: config.runtimeLabel || config.name,
      stage,
      kind,
      summary,
      parentId,
      status: "cached",
      startedAt: now,
      finishedAt: now,
      durationMs: 0,
      error: null,
      logRef: null,
      _logRecord: null,
    };
    operations.push(operation);
    byId.set(operation.id, operation);
    emitChange();
    return operation;
  }

  function listOperations() {
    return operations.map(cloneOperation);
  }

  return {
    start,
    finish,
    recordCached,
    listOperations,
  };
}

function cloneOperation(operation) {
  return {
    id: operation.id,
    serviceName: operation.serviceName,
    runtimeLabel: operation.runtimeLabel,
    stage: operation.stage,
    kind: operation.kind,
    summary: operation.summary,
    parentId: operation.parentId,
    status: operation.status,
    startedAt: operation.startedAt,
    finishedAt: operation.finishedAt,
    durationMs: operation.durationMs,
    error: operation.error,
    logRef: operation.logRef,
  };
}
