import { promises as fs, existsSync } from "node:fs";
import { isAbsolute } from "node:path";
import { fileURLToPath } from "node:url";
import xxhash from "xxhash-wasm";
import { ASSET_IMPORTS_FILE, DATA_STORE_FILE } from "./consts.js";
import { DataStore, globalDataStore } from "./data-store.js";
import { getEntryDataAndImages, globalContentConfigObserver, posixRelative } from "./utils.js";
async function syncContentLayer({
  settings,
  logger: globalLogger,
  store,
  watcher
}) {
  watcher?.setMaxListeners(50);
  const logger = globalLogger.forkIntegrationLogger("content");
  logger.info("Syncing content");
  if (!store) {
    store = await DataStore.fromDisk(new URL(DATA_STORE_FILE, settings.config.cacheDir));
    globalDataStore.set(store);
  }
  const contentConfig = globalContentConfigObserver.get();
  if (contentConfig?.status !== "loaded") {
    logger.debug("Content config not loaded, skipping sync");
    return;
  }
  const { h64ToString } = await xxhash();
  const generateDigest = (data) => {
    const dataString = typeof data === "string" ? data : JSON.stringify(data);
    return h64ToString(dataString);
  };
  await Promise.all(
    Object.entries(contentConfig.config.collections).map(async ([name, collection]) => {
      if (collection.type !== "experimental_data" && collection.type !== "experimental_content") {
        return;
      }
      let { schema } = collection;
      if (!schema && typeof collection.loader === "object") {
        schema = collection.loader.schema;
        if (typeof schema === "function") {
          schema = await schema();
        }
      }
      const collectionWithResolvedSchema = { ...collection, schema };
      const parseData = async ({ id, data, filePath = "" }) => {
        const { imageImports, data: parsedData } = await getEntryDataAndImages(
          {
            id,
            collection: name,
            unvalidatedData: data,
            _internal: {
              rawData: void 0,
              filePath
            }
          },
          collectionWithResolvedSchema,
          false
        );
        if (imageImports?.length) {
          store.addAssetImports(
            imageImports,
            // This path may already be relative, if we're re-parsing an existing entry
            isAbsolute(filePath) ? posixRelative(fileURLToPath(settings.config.root), filePath) : filePath
          );
        }
        return parsedData;
      };
      const payload = {
        collection: name,
        store: store.scopedStore(name),
        meta: store.metaStore(name),
        logger: globalLogger.forkIntegrationLogger(collection.loader.name ?? "content"),
        settings,
        parseData,
        generateDigest,
        watcher
      };
      if (typeof collection.loader === "function") {
        return simpleLoader(collection.loader, payload);
      }
      if (!collection.loader.load) {
        throw new Error(`Collection loader for ${name} does not have a load method`);
      }
      return collection.loader.load(payload);
    })
  );
  if (!existsSync(settings.config.cacheDir)) {
    await fs.mkdir(settings.config.cacheDir, { recursive: true });
  }
  const cacheFile = new URL(DATA_STORE_FILE, settings.config.cacheDir);
  await store.writeToDisk(cacheFile);
  if (!existsSync(settings.dotAstroDir)) {
    await fs.mkdir(settings.dotAstroDir, { recursive: true });
  }
  const assetImportsFile = new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir);
  await store.writeAssetImports(assetImportsFile);
  logger.info("Synced content");
}
async function simpleLoader(handler, context) {
  const data = await handler();
  context.store.clear();
  for (const raw of data) {
    const item = await context.parseData({ id: raw.id, data: raw });
    context.store.set({ id: raw.id, data: item });
  }
}
export {
  simpleLoader,
  syncContentLayer
};
