import type { TerminalState } from "./types.js";

export interface WorkDirectory {
  readonly path: string;
  remove(): Promise<void>;
}

export interface TerminalResult<T> {
  readonly state: TerminalState;
  readonly value?: T;
}

/**
 * The sole lifecycle wrapper for per-job work. Cleanup is attempted for every
 * return and throw. A cleanup error is surfaced rather than reporting a false
 * terminal success; an earlier operation error is retained as its cause.
 */
export async function withWorkDirectory<T>(
  workDirectory: WorkDirectory,
  operation: () => Promise<TerminalResult<T>>,
): Promise<TerminalResult<T>> {
  let operationError: unknown;
  try {
    return await operation();
  } catch (error) {
    operationError = error;
    throw error;
  } finally {
    try {
      await workDirectory.remove();
    } catch (cleanupError) {
      throw new WorkDirectoryCleanupError(workDirectory.path, cleanupError, operationError);
    }
  }
}

export class WorkDirectoryCleanupError extends Error {
  readonly cleanupCause: unknown;
  readonly operationCause: unknown;

  constructor(path: string, cleanupCause: unknown, operationCause?: unknown) {
    super(`Failed to clean job work directory: ${path}`, { cause: cleanupCause });
    this.name = "WorkDirectoryCleanupError";
    this.cleanupCause = cleanupCause;
    this.operationCause = operationCause;
  }
}
