import path from "path";
import { randomBytes } from "crypto";
import { getUploadDir } from "./storage";

/** Allow only safe staging folder names from clients. */
export function sanitizeUploadSessionKey(raw?: string | null): string {
  const cleaned = (raw ?? "").replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 64);
  if (cleaned.length >= 8) return cleaned;
  return `${Date.now().toString(36)}-${randomBytes(6).toString("hex")}`;
}

function userUploadRoot(userId: string) {
  return path.resolve(getUploadDir(), userId);
}

function isInsideDir(filePath: string, dir: string) {
  const resolvedFile = path.resolve(filePath);
  const resolvedDir = path.resolve(dir);
  return resolvedFile === resolvedDir || resolvedFile.startsWith(resolvedDir + path.sep);
}

/** Ensure a path stays under uploads/{userId}/ (blocks traversal & cross-user access). */
export function assertPathInUserUploads(userId: string, filePath: string): string {
  if (!filePath?.trim()) {
    throw new Error("Invalid upload path");
  }

  const resolved = path.resolve(filePath);
  const root = userUploadRoot(userId);

  if (!isInsideDir(resolved, root)) {
    throw new Error("Invalid upload path");
  }

  return resolved;
}

export function getUserStagingDir(userId: string, sessionKey: string) {
  const safeSession = sanitizeUploadSessionKey(sessionKey);
  const dir = path.join(userUploadRoot(userId), "staging", safeSession);
  // Defense in depth: resolve and re-check
  const resolved = path.resolve(dir);
  if (!isInsideDir(resolved, userUploadRoot(userId))) {
    throw new Error("Invalid upload session");
  }
  return resolved;
}
