/**
 * LocalAdapter — blobs on disk under a base path. Dev default; no network.
 * `presignGet` returns a loopback `file://` URL (consumers on the same host).
 */

import { mkdirSync } from 'fs';
import { readFile } from 'fs/promises';
import { join } from 'path';
import { pathToFileURL } from 'url';

import { StorageError, type Body, type ObjectStore } from './index';

export class LocalAdapter implements ObjectStore {
  readonly bucket = 'local';
  private readonly basePath: string;

  constructor(basePath: string) {
    this.basePath = basePath;
  }

  async put(key: string, _contentType: string, body: Body): Promise<void> {
    try {
      const fullPath = join(this.basePath, key);
      mkdirSync(fullPath.substring(0, fullPath.lastIndexOf('/')), { recursive: true });
      const data = body instanceof ReadableStream ? new Uint8Array(await new Response(body).arrayBuffer()) : body;
      await Bun.write(fullPath, data);
    } catch (err) {
      throw new StorageError(`local put failed for key ${key}`, key, err);
    }
  }

  async get(key: string): Promise<Buffer> {
    try {
      return await readFile(join(this.basePath, key));
    } catch (err) {
      throw new StorageError(`local get failed for key ${key}`, key, err);
    }
  }

  async head(key: string): Promise<boolean> {
    return Bun.file(join(this.basePath, key)).exists();
  }

  async presignGet(key: string): Promise<string> {
    return pathToFileURL(join(this.basePath, key)).href;
  }
}
