import { writeFileSync } from "node:fs";
import { writeFile, readFile } from "node:fs/promises";
import path from "node:path";
import { onExit } from "./util";

const store = <T extends Object>(
  name: string,
  init: () => T,
  { persistInterval = 60 * 1000 } = {}
) => {
  let state = init();
  (state as any)._storeName = name;

  const filePath = path.join(process.cwd(), `${name}.json`);

  const persist = (sync = false) => {
    const write = sync ? writeFileSync : writeFile;
    return write(filePath, JSON.stringify(state));
  };
  const load = async () => {
    try {
      const newState = await readFile(filePath, { encoding: "utf8" });
      state = JSON.parse(newState);
      if ((state as any)._storeName !== name) {
        console.error(`File at "${filePath}" expected to be a Rappli store`);
        process.exit(1);
      }
    } catch (err) {
      if (typeof err === "object" && (err as any).code !== "ENOENT") {
        console.dir(err);
        process.exit(1);
      }
    }
  };

  const globals = globalThis as any;

  (async () => {
    await load();
    const intervalKey = `_store-persist-${name}`;

    if (globals[intervalKey] != null) {
      clearInterval(globals[intervalKey]);
    }
    globals[intervalKey] = setInterval(function () {
      persist();
    }, persistInterval);
  })();

  const exitKey = `_store-exit-${name}`;
  if (globals[exitKey]) {
    globals[exitKey]();
  }
  globals[exitKey] = onExit(() => persist(true));

  const getState = () => state;

  return [getState] as [typeof getState];
};

export const [state] = store("data", () => ({
  version: 0,
  likes: 0,
}));
