import { fail } from "k6";
import {
  defaultOptions,
  emitFailureCollectionArtifact,
  recordRuntimeFailure,
  startFailureCollection,
} from "./checks.js";
import { createDalContext, openDb } from "./dal.js";

export function defineDalSuite(configOrRun, maybeRun) {
  const { config, run } = normalizeSuiteArgs(configOrRun, maybeRun);
  const db = config.db || openDb();
  const dal = createDalContext(db);

  return {
    options: config.options || defaultOptions,
    setup() {
      if (typeof config.setup !== "function") return null;
      startFailureCollection("setup");
      try {
        return config.setup({ db, dal });
      } catch (error) {
        recordRuntimeFailure();
        fail(formatFatalSuiteError("setup", error));
      } finally {
        emitFailureCollectionArtifact();
      }
    },
    exec(setupData) {
      startFailureCollection("exec");
      try {
        return run({
          db,
          dal,
          setupData,
        });
      } catch (error) {
        recordRuntimeFailure();
        fail(formatFatalSuiteError("exec", error));
      } finally {
        emitFailureCollectionArtifact();
      }
    },
  };
}

function normalizeSuiteArgs(configOrRun, maybeRun) {
  if (typeof configOrRun === "function") {
    return { config: {}, run: configOrRun };
  }
  if (typeof maybeRun !== "function") {
    throw new Error("suite factory requires a run callback");
  }
  return { config: configOrRun || {}, run: maybeRun };
}

function formatFatalSuiteError(phase, error) {
  if (error instanceof Error) {
    return `Uncaught testkit suite error during ${phase}: ${error.message}`;
  }
  return `Uncaught testkit suite error during ${phase}: ${String(error)}`;
}
