import type { Dirent } from 'node:fs';

/** Statistics returned after a copy operation completes. */
export interface CopyResult {
  /** Total files discovered. */
  files: number;
  /** Total directories created. */
  dirs: number;
  /** Total symlinks discovered. */
  symlinks: number;
  /** Number of items copied successfully. */
  succeeded: number;
  /** Number of items that failed to copy. */
  failed: number;
  /** Detailed error list for failed items. */
  errors: CopyError[];
}

/** A single copy failure. */
export interface CopyError {
  /** Source path of the item that failed. */
  src: string;
  /** Destination path that was being written to. */
  dest: string;
  /** The underlying error. */
  error: Error;
}

/** Progress information emitted during a copy. */
export interface CopyProgress {
  /** Number of files completed so far. */
  completed: number;
  /** Total number of files to copy. */
  total: number;
  /** Number of successful copies so far. */
  succeeded: number;
  /** Number of failed copies so far. */
  failed: number;
}

/** Options controlling copy behaviour. */
export interface CopyOptions {
  /**
   * Maximum number of files to copy in parallel.
   * Defaults to `cpu × 2` (min 4). Pass `'auto'` for `cpu × 4` (max 128).
   * Lower values reduce memory; higher values may increase throughput on fast SSDs.
   */
  concurrency?: number | 'auto';

  /**
   * Whether to overwrite existing files at the destination.
   * When `false`, existing files are left untouched (copy is skipped).
   * @default true
   */
  overwrite?: boolean;

  /**
   * Filter function called for every entry during tree traversal.
   * Return `false` to skip the entry entirely (files **and** directories).
   *
   * @param src - Full source path of the entry.
   * @param entry - The `Dirent` object from `readdir(..., { withFileTypes: true })`.
   */
  filter?: (src: string, entry: Dirent) => boolean;

  /**
   * Progress callback — fires after **each** file copy completes.
   * For large trees (100k+ files), the callback overhead may be noticeable;
   * throttle externally if needed.
   */
  onProgress?: (stats: CopyProgress) => void;

  /**
   * Whether to skip symlinks during copy.
   * @default false
   */
  excludeSymlinks?: boolean;

  /**
   * Preserve file timestamps (atime, mtime) from source files.
   * Adds one `stat` + one `utimes` call per file; ~20-30% slower when enabled.
   * @default false
   */
  preserveTimestamps?: boolean;
}

/**
 * Copy a file or directory tree from `source` to `dest`.
 *
 * @param source - Source path (file or directory).
 * @param dest   - Destination path.
 * @param options - Optional configuration.
 * @returns A result object with copy statistics.
 */
export default function copyDep(
  source: string,
  dest: string,
  options?: CopyOptions
): Promise<CopyResult>;

/** Named alias — equivalent to the default export. */
export function copy(source: string, dest: string, options?: CopyOptions): Promise<CopyResult>;

/** Named alias — equivalent to the default export. */
export function copyDep(source: string, dest: string, options?: CopyOptions): Promise<CopyResult>;
