import { isAbsolute, resolve } from "node:path";

/**
 * Working-directory normalization boundaries.
 *
 * Cwd strings reach the server from three kinds of sources with different trust:
 *
 * 1. HTTP requests (web UI, federation proxies): normalize strictly with
 *    `normalizeRequestCwd` at route parsing. Relative paths are rejected instead
 *    of being silently resolved against the daemon's own working directory.
 * 2. Data pi-web writes itself (archive store records): canonicalized on write
 *    and on load with `canonicalizeStoredCwd`, so internal `===` comparisons are
 *    safe by construction.
 * 3. Data other writers own (Pi session file headers via the SDK): canonicalized
 *    on read at the gateway, and compared tolerantly with `cwdPathsEqual` where a
 *    raw value can still appear (e.g. runtime cwd of sessions opened from files).
 *
 * Inside these boundaries, plain string equality on cwd values is safe.
 */

/**
 * Strictly normalize a client-supplied working directory at an HTTP boundary.
 * Throws for non-string, empty, or relative input; returns the resolved
 * (separator- and trailing-slash-normalized) absolute path otherwise.
 */
export function normalizeRequestCwd(cwd: unknown): string {
  if (typeof cwd !== "string" || cwd === "") throw new Error("cwd is required");
  if (!isAbsolute(cwd)) throw new Error("cwd must be an absolute path");
  return resolve(cwd);
}

/**
 * Leniently canonicalize a working directory loaded from stored data.
 * Absolute paths are resolved to canonical form; anything else (legacy empty or
 * relative values) is preserved as-is so a single bad record cannot fail a whole
 * load, and never silently resolves against this process's working directory.
 */
export function canonicalizeStoredCwd(cwd: string): string {
  return isAbsolute(cwd) ? resolve(cwd) : cwd;
}

/** Compare two working-directory paths, tolerating separator and normalization differences (e.g. Windows backslash vs forward slash). */
export function cwdPathsEqual(a: string, b: string): boolean {
  return resolve(a) === resolve(b);
}
