import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
import { fs } from '../utils/fs-utils.js';
import { Utils } from '../utils/Utils.js';
export class FileCacheAdapter {
  #VERSION = Utils.getORMVersion();
  #cache = {};
  #options;
  #baseDir;
  #pretty;
  constructor(options = {}, baseDir, pretty = false) {
    this.#options = options;
    this.#baseDir = baseDir;
    this.#pretty = pretty;
    this.#options.cacheDir ??= process.cwd() + '/temp';
  }
  /**
   * @inheritDoc
   */
  get(name) {
    const path = this.path(name);
    if (!existsSync(path)) {
      return null;
    }
    const payload = fs.readJSONSync(path);
    const hash = this.getHash(payload.origin);
    if (!hash || payload.hash !== hash) {
      return null;
    }
    return payload.data;
  }
  /**
   * @inheritDoc
   */
  set(name, data, origin) {
    if (this.#options.combined) {
      this.#cache[name.replace(/\.[jt]s$/, '')] = data;
      return;
    }
    const path = this.path(name);
    const hash = this.getHash(origin);
    writeFileSync(
      path,
      JSON.stringify({ data, origin, hash, version: this.#VERSION }, null, this.#pretty ? 2 : undefined),
    );
  }
  /**
   * @inheritDoc
   */
  remove(name) {
    const path = this.path(name);
    unlinkSync(path);
  }
  /**
   * @inheritDoc
   */
  clear() {
    const path = this.path('*');
    const files = fs.glob(path);
    for (const file of files) {
      /* v8 ignore next */
      try {
        unlinkSync(file);
      } catch {
        // ignore if file is already gone
      }
    }
    this.#cache = {};
  }
  combine() {
    if (!this.#options.combined) {
      return;
    }
    let path = typeof this.#options.combined === 'string' ? this.#options.combined : './metadata.json';
    path = fs.normalizePath(this.#options.cacheDir, path);
    this.#options.combined = path; // override in the options, so we can log it from the CLI in `cache:generate` command
    writeFileSync(path, JSON.stringify(this.#cache, null, this.#pretty ? 2 : undefined));
    return path;
  }
  path(name) {
    fs.ensureDir(this.#options.cacheDir);
    return `${this.#options.cacheDir}/${name}.json`;
  }
  getHash(origin) {
    origin = fs.absolutePath(origin, this.#baseDir);
    if (!existsSync(origin)) {
      return null;
    }
    const contents = readFileSync(origin);
    return Utils.hash(contents.toString() + this.#VERSION);
  }
}
