// src/prebuild/index.ts
import * as fs from "fs";
import * as path from "path";
import * as crypto from "crypto";

// src/version.ts
var SDK_VERSION = "0.60.16";

// src/constants.ts
var PREBUILD_PAGE_SIZE = 50;
var DEFAULT_PREBUILD_DIR = ".riverbank-cache";

// src/prebuild/index.ts
var MANIFEST_VERSION = "1.0.0";
var MANIFEST_FILENAME = "manifest.json";
function pathToFilename(routePath) {
  if (routePath === "/") return "_home.json";
  return routePath.slice(1).replace(/[^a-zA-Z0-9\-\/]/g, "_").replace(/\//g, "-") + ".json";
}
function ensureDir(dirPath) {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
  }
}
function writeJsonFile(filePath, data) {
  const content = JSON.stringify(data, null, 2);
  fs.writeFileSync(filePath, content, "utf-8");
  return Buffer.byteLength(content, "utf-8");
}
function calculateChecksum(data) {
  const { checksum: _, ...rest } = data;
  const content = JSON.stringify(rest);
  return crypto.createHash("sha256").update(content).digest("hex");
}
async function fetchAllEntries(client, siteId, contentType, onProgress) {
  const allEntries = [];
  let offset = 0;
  let hasMore = true;
  while (hasMore) {
    onProgress?.(`${contentType} (batch ${Math.floor(offset / PREBUILD_PAGE_SIZE) + 1})`);
    const response = await client.getEntries({
      siteId,
      contentType,
      limit: PREBUILD_PAGE_SIZE,
      offset,
      preview: false
      // Published content only
    });
    allEntries.push(...response.entries);
    offset += PREBUILD_PAGE_SIZE;
    hasMore = response.entries.length === PREBUILD_PAGE_SIZE;
  }
  return allEntries;
}
async function prebuildSite(client, siteId, outputDir) {
  const site = await client.getSite({ id: siteId });
  const filename = "site.json";
  const filePath = path.join(outputDir, filename);
  const cacheFile = {
    data: site,
    generatedAt: (/* @__PURE__ */ new Date()).toISOString()
  };
  const size = writeJsonFile(filePath, cacheFile);
  return { files: [filename], size, siteData: site };
}
async function prebuildPages(client, siteId, routes, outputDir, onProgress) {
  const pagesDir = path.join(outputDir, "pages");
  ensureDir(pagesDir);
  const files = [];
  const pathMappings = {};
  let totalSize = 0;
  const publishedPaths = Object.entries(routes).filter(([_, route]) => route.status === "published").map(([_, route]) => route.path);
  const pageIndex = [];
  const total = publishedPaths.length;
  let current = 0;
  for (const pagePath of publishedPaths) {
    current++;
    onProgress?.({
      current,
      total,
      item: `Page: ${pagePath}`,
      contentType: "pages"
    });
    try {
      const pageData = await client.getPage({ siteId, path: pagePath, preview: false });
      const filename = pathToFilename(pagePath);
      const filePath = path.join(pagesDir, filename);
      const cacheFile = {
        data: pageData,
        path: pagePath,
        generatedAt: (/* @__PURE__ */ new Date()).toISOString()
      };
      totalSize += writeJsonFile(filePath, cacheFile);
      files.push(`pages/${filename}`);
      pathMappings[pagePath] = `pages/${filename}`;
      if ("page" in pageData) {
        pageIndex.push({
          path: pagePath,
          pageId: pageData.page.routeId || "",
          title: pageData.page.name || "Untitled"
        });
      }
    } catch (error) {
      console.warn(`[Prebuild] Failed to fetch page ${pagePath}:`, error.message);
    }
  }
  const indexFile = {
    pages: pageIndex,
    totalCount: pageIndex.length,
    generatedAt: (/* @__PURE__ */ new Date()).toISOString()
  };
  const indexPath = path.join(pagesDir, "_index.json");
  totalSize += writeJsonFile(indexPath, indexFile);
  files.push("pages/_index.json");
  return { files, size: totalSize, pathMappings };
}
async function prebuildEntries(client, siteId, contentTypes, outputDir, onProgress) {
  const entriesDir = path.join(outputDir, "entries");
  ensureDir(entriesDir);
  const files = [];
  let totalSize = 0;
  const total = contentTypes.length;
  let current = 0;
  for (const contentType of contentTypes) {
    current++;
    const entries = await fetchAllEntries(
      client,
      siteId,
      contentType,
      (item) => {
        onProgress?.({
          current,
          total,
          item: `Entries: ${item}`,
          contentType: "entries"
        });
      }
    );
    const typeDir = path.join(entriesDir, contentType);
    ensureDir(typeDir);
    const cacheFile = {
      entries,
      contentType,
      totalCount: entries.length,
      generatedAt: (/* @__PURE__ */ new Date()).toISOString()
    };
    const filename = `entries/${contentType}/all.json`;
    const filePath = path.join(entriesDir, contentType, "all.json");
    totalSize += writeJsonFile(filePath, cacheFile);
    files.push(filename);
  }
  return { files, size: totalSize };
}
async function prebuildNavigation(siteData, outputDir, onProgress) {
  const navDir = path.join(outputDir, "navigation");
  ensureDir(navDir);
  const files = [];
  let totalSize = 0;
  const menus = siteData.navigation || [];
  onProgress?.({
    current: 1,
    total: 1,
    item: "Navigation menus",
    contentType: "navigation"
  });
  const cacheFile = {
    menus: menus.map((menu) => ({
      identifier: menu.identifier,
      id: menu.id,
      name: menu.name,
      items: menu.items
    })),
    generatedAt: (/* @__PURE__ */ new Date()).toISOString()
  };
  const filename = "navigation/menus.json";
  const filePath = path.join(navDir, "menus.json");
  totalSize += writeJsonFile(filePath, cacheFile);
  files.push(filename);
  return { files, size: totalSize };
}
async function prebuildForms(client, siteId, outputDir, onProgress) {
  const formsDir = path.join(outputDir, "forms");
  ensureDir(formsDir);
  const files = [];
  let totalSize = 0;
  onProgress?.({
    current: 1,
    total: 1,
    item: "Forms",
    contentType: "forms"
  });
  try {
    const response = await client.getForms({ siteId });
    const forms = response.forms || [];
    const cacheFile = {
      forms: forms.map((form) => ({
        id: form.id,
        slug: form.slug,
        name: form.name,
        schema: form.schema,
        settings: form.settings
      })),
      totalCount: forms.length,
      generatedAt: (/* @__PURE__ */ new Date()).toISOString()
    };
    const filename = "forms/forms.json";
    const filePath = path.join(formsDir, "forms.json");
    totalSize += writeJsonFile(filePath, cacheFile);
    files.push(filename);
  } catch (error) {
    console.warn("[Prebuild] Failed to fetch forms:", error.message);
  }
  return { files, size: totalSize };
}
async function prebuildCache(options) {
  const {
    client,
    siteId,
    outputDir = DEFAULT_PREBUILD_DIR,
    include = ["site", "pages", "entries", "navigation", "forms"],
    contentTypes,
    onProgress
  } = options;
  const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
  const files = [];
  let totalSize = 0;
  const errors = [];
  let siteData = null;
  let pagePathMappings = {};
  ensureDir(outputDir);
  if (include.includes("site") || include.includes("pages") || include.includes("navigation")) {
    try {
      const result = await prebuildSite(client, siteId, outputDir);
      siteData = result.siteData;
      if (include.includes("site")) {
        files.push(...result.files);
        totalSize += result.size;
      }
      onProgress?.({ current: 1, total: 4, item: "Site data", contentType: "site" });
    } catch (error) {
      errors.push(`Site prebuild failed: ${error.message}`);
    }
  }
  if (include.includes("pages") && siteData) {
    try {
      const result = await prebuildPages(
        client,
        siteId,
        siteData.routes,
        outputDir,
        onProgress
      );
      files.push(...result.files);
      totalSize += result.size;
      pagePathMappings = result.pathMappings;
    } catch (error) {
      errors.push(`Pages prebuild failed: ${error.message}`);
    }
  }
  if (include.includes("entries")) {
    try {
      const typesToPrebuild = contentTypes || [];
      if (typesToPrebuild.length > 0) {
        const result = await prebuildEntries(
          client,
          siteId,
          typesToPrebuild,
          outputDir,
          onProgress
        );
        files.push(...result.files);
        totalSize += result.size;
      } else {
        console.warn("[Prebuild] No contentTypes provided - skipping entries prebuild");
      }
    } catch (error) {
      errors.push(`Entries prebuild failed: ${error.message}`);
    }
  }
  if (include.includes("navigation") && siteData) {
    try {
      const result = await prebuildNavigation(siteData, outputDir, onProgress);
      files.push(...result.files);
      totalSize += result.size;
    } catch (error) {
      errors.push(`Navigation prebuild failed: ${error.message}`);
    }
  }
  if (include.includes("forms")) {
    try {
      const result = await prebuildForms(client, siteId, outputDir, onProgress);
      files.push(...result.files);
      totalSize += result.size;
    } catch (error) {
      errors.push(`Forms prebuild failed: ${error.message}`);
    }
  }
  const keyToFile = {};
  if (files.includes("site.json")) {
    keyToFile[`site:${siteId}`] = "site.json";
  }
  for (const [pagePath, file] of Object.entries(pagePathMappings)) {
    keyToFile[`page:${siteId}:${pagePath}:false`] = file;
  }
  for (const file of files.filter((f) => f.startsWith("entries/") && f.endsWith("/all.json"))) {
    const contentType = file.split("/")[1];
    keyToFile[`entries-all:${siteId}:${contentType}`] = file;
  }
  if (files.includes("forms/forms.json")) {
    keyToFile[`forms:${siteId}`] = "forms/forms.json";
  }
  const manifest = {
    version: MANIFEST_VERSION,
    generatedAt,
    siteId,
    sdkVersion: SDK_VERSION,
    keyToFile,
    includedTypes: include,
    fileCount: files.length,
    totalSize
  };
  const checksum = calculateChecksum(manifest);
  manifest.checksum = checksum;
  const manifestPath = path.join(outputDir, MANIFEST_FILENAME);
  writeJsonFile(manifestPath, manifest);
  return {
    success: errors.length === 0,
    outputDir,
    files,
    totalSize,
    generatedAt,
    checksum,
    errors: errors.length > 0 ? errors : void 0
  };
}
export {
  prebuildCache
};
