import {
  createMachineSessionLoadSummary,
  machineSessionLoadLogLines,
} from "./session-load-summary.js";
import {
  createSessionSnapshotSummary,
  sessionSnapshotSummaryLogLines,
} from "./session-summary.js";

export function createSessionSnapshotFieldState(summary) {
  return {
    sessionIni: summary.iniOpfsPath,
    sessionParameters: summary.parameterOpfsPath,
    sessionToolTable: summary.toolTableOpfsPath,
    sessionGcode: summary.gcodeOpfsPath,
    sessionSnapshot: summary.snapshotLabel,
  };
}

export function sessionSnapshotSaveLogLines(summary) {
  return [
    ...sessionSnapshotSummaryLogLines(summary),
    `INI: ${summary.iniOpfsPath}`,
    `Parameter file: ${summary.parameterOpfsPath}`,
    `Tool table file: ${summary.toolTableOpfsPath}`,
    `G-code: ${summary.gcodeOpfsPath}`,
  ];
}

export function sessionSnapshotRestoreLogLines(summary) {
  return [
    ...sessionSnapshotSummaryLogLines(summary),
    `INI: ${summary.iniOpfsPath}`,
    `Parameter file: ${summary.parameterOpfsPath}`,
    `Tool table file: ${summary.toolTableOpfsPath}`,
    `G-code: ${summary.gcodeOpfsPath ?? "-"}`,
  ];
}

export function createMachineSessionLoadFieldState(summary) {
  return {
    sessionIni: summary.iniWasmPath,
    sessionParameters: summary.parameterWasmPath,
    sessionToolTable: summary.toolTableWasmPath,
  };
}

export function machineSessionLoadWorkflowLogLines(summary) {
  return [
    "Loaded machine session into the interpreter WASM filesystem.",
    ...machineSessionLoadLogLines(summary),
  ];
}

export async function loadMachineSessionIntoWasmWorkflow({ loadSession }) {
  if (typeof loadSession !== "function") {
    throw new Error("A machine session loader is required.");
  }
  const loadedSession = await loadSession();
  const loadSummary = createMachineSessionLoadSummary(loadedSession);
  return {
    loadedSession,
    loadSummary,
    fields: createMachineSessionLoadFieldState(loadSummary),
    logLines: machineSessionLoadWorkflowLogLines(loadSummary),
  };
}

export async function saveMachineSessionSnapshotWorkflow({
  machineId,
  snapshotId,
  snapshotFilename,
  snapshotLabel,
  iniText,
  toolTableText,
  parameterText,
  gcodeFilename,
  gcodeText,
  metadata,
  saveMachineTextFiles,
  saveGcodeProgram,
  saveMachineSessionSnapshot,
}) {
  await Promise.all([
    saveMachineTextFiles(machineId, {
      ini: iniText,
      toolTable: toolTableText,
      parameters: parameterText,
    }),
    saveGcodeProgram(gcodeFilename, gcodeText),
  ]);
  const snapshot = await saveMachineSessionSnapshot(
    snapshotId,
    machineId,
    {
      filename: snapshotFilename,
      gcodeFilename,
      metadata,
    },
  );
  const summary = createSessionSnapshotSummary(snapshot, snapshotLabel);
  return {
    snapshot,
    summary,
    fields: createSessionSnapshotFieldState(summary),
    logLines: sessionSnapshotSaveLogLines(summary),
  };
}

export async function restoreMachineSessionSnapshotWorkflow({
  machineId,
  snapshotId,
  snapshotFilename,
  snapshotLabel,
  loadMachineSessionSnapshot,
  loadMachineTextFiles,
  loadSession = null,
}) {
  const snapshot = await loadMachineSessionSnapshot(
    snapshotId,
    machineId,
    { filename: snapshotFilename },
  );
  const files = await loadMachineTextFiles(machineId);
  const summary = createSessionSnapshotSummary(snapshot, snapshotLabel ?? snapshotLabelFromSession(snapshot));
  const fields = createSessionSnapshotFieldState(summary);
  const result = {
    snapshot,
    editorIniText: files.ini,
    summary,
    fields,
    loadSummary: null,
    loadedSession: null,
    logLines: sessionSnapshotRestoreLogLines(summary),
  };
  if (loadSession) {
    const loadWorkflow = await loadMachineSessionIntoWasmWorkflow({ loadSession });
    result.loadedSession = loadWorkflow.loadedSession;
    result.loadSummary = loadWorkflow.loadSummary;
    result.fields = {
      ...fields,
      ...loadWorkflow.fields,
      sessionGcode: summary.gcodeOpfsPath,
    };
    result.logLines = [
      ...sessionSnapshotSummaryLogLines(summary),
      ...loadWorkflow.logLines,
      `G-code: ${summary.gcodeOpfsPath ?? "-"}`,
    ];
  }
  return result;
}

function snapshotLabelFromSession(snapshot) {
  return snapshot?.metadata?.snapshotLabel ?? snapshot?.sessionId ?? null;
}
