/**
 * Local-disk storage driver. Files live under a configured directory; keys map
 * to relative paths inside it. Path traversal is rejected — a key can never
 * escape the base dir.
 */

import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
import { dirname, isAbsolute, join, resolve, sep } from "node:path";
import type { LocalStoreConfig, PutMeta, StorageDriver } from "../driver.ts";
import { contentTypeOf } from "../mime.ts";

export function localDriver(config: LocalStoreConfig, appRoot: string): StorageDriver {
  const base = resolve(isAbsolute(config.dir) ? config.dir : join(appRoot, config.dir));

  /** Resolve a key to an absolute path that MUST stay inside `base`. */
  function pathFor(key: string): string {
    const abs = resolve(base, key);
    if (abs !== base && !abs.startsWith(base + sep)) {
      throw new Error(`unsafe storage key: ${key}`);
    }
    return abs;
  }

  return {
    async put(key, data, _meta: PutMeta) {
      const file = pathFor(key);
      await mkdir(dirname(file), { recursive: true });
      await writeFile(file, data);
    },
    async get(key) {
      try {
        const data = await readFile(pathFor(key));
        return {
          body: new Uint8Array(data),
          contentType: contentTypeOf(key),
          size: data.byteLength,
        };
      } catch (err) {
        if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
        throw err;
      }
    },
    async delete(key) {
      try {
        await unlink(pathFor(key));
      } catch (err) {
        if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
      }
    },
    publicUrl() {
      // Local objects are served by the framework route (/__wrnexus/uploads/...).
      return null;
    },
  };
}
