/**
 * Represents a file or directory entry in the virtual filesystem
 */
export interface IFileEntry {
  type: 'file' | 'directory';
  name: string;
  path: string;
}

/**
 * Handle to a file system watcher
 */
export interface IFileWatcher {
  /** Stop watching for changes */
  stop(): void;
}

/**
 * Handle to a spawned process with I/O streams
 */
export interface IProcessHandle {
  /** Stream of output data from the process */
  output: ReadableStream<string>;
  /** Input stream to write data to the process */
  input: { getWriter(): WritableStreamDefaultWriter<string> };
  /** Promise that resolves with exit code when process terminates */
  exit: Promise<number>;
  /** Kill the process */
  kill(): void;
}

/**
 * Abstract execution environment interface.
 * Implementations can target WebContainer (browser), Backend API (server), or Mock (testing).
 */
export interface IExecutionEnvironment {
  // ============ Filesystem Operations ============

  /**
   * Read the contents of a file
   * @param path - Absolute path to the file
   * @returns File contents as string
   */
  readFile(path: string): Promise<string>;

  /**
   * Write contents to a file (creates or overwrites)
   * @param path - Absolute path to the file
   * @param contents - String contents to write
   */
  writeFile(path: string, contents: string): Promise<void>;

  /**
   * List contents of a directory
   * @param path - Absolute path to the directory
   * @returns Array of file entries
   */
  readDir(path: string): Promise<IFileEntry[]>;

  /**
   * Create a directory (and parent directories if needed)
   * @param path - Absolute path to create
   */
  mkdir(path: string): Promise<void>;

  /**
   * Remove a file or directory
   * @param path - Absolute path to remove
   * @param options - Optional: { recursive: true } for directories
   */
  rm(path: string, options?: { recursive?: boolean }): Promise<void>;

  /**
   * Check if a path exists
   * @param path - Absolute path to check
   */
  exists(path: string): Promise<boolean>;

  /**
   * Watch a file or directory for changes
   * @param path - Absolute path to watch
   * @param callback - Called when changes occur
   * @param options - Optional: { recursive: true } to watch subdirectories
   * @returns Watcher handle with stop() method
   */
  watch(
    path: string,
    callback: (event: 'rename' | 'change', filename: string | null) => void,
    options?: { recursive?: boolean }
  ): IFileWatcher;

  // ============ Process Execution ============

  /**
   * Spawn a new process
   * @param command - Command to run (e.g., 'jsh', 'node', 'npm')
   * @param args - Optional arguments
   * @returns Process handle with I/O streams
   */
  spawn(command: string, args?: string[]): Promise<IProcessHandle>;

  // ============ Lifecycle ============

  /**
   * Initialize the environment (e.g., boot WebContainer)
   * Must be called before any other operations
   */
  init(): Promise<void>;

  /**
   * Destroy the environment and clean up resources
   */
  destroy(): Promise<void>;

  // ============ State ============

  /** Whether the environment has been initialized and is ready */
  readonly ready: boolean;

  /** Type identifier for the environment implementation */
  readonly type: 'webcontainer' | 'backend' | 'mock';
}
