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

// src/constants.ts
var DEFAULT_MAX_PREBUILD_AGE_SEC = 86400;
var DEFAULT_PREBUILD_DIR = ".riverbank-cache";

// src/prebuild/loader.ts
function isRecord(value) {
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
}
function isStringArray(value) {
  return Array.isArray(value) && value.every((item) => typeof item === "string");
}
function isPrebuildManifest(value) {
  if (!isRecord(value)) return false;
  if (typeof value.version !== "string") return false;
  if (typeof value.generatedAt !== "string") return false;
  if (typeof value.checksum !== "string") return false;
  if (typeof value.siteId !== "string") return false;
  if (typeof value.sdkVersion !== "string") return false;
  if (!isRecord(value.keyToFile)) return false;
  if (!isStringArray(value.includedTypes)) return false;
  if (typeof value.fileCount !== "number") return false;
  if (typeof value.totalSize !== "number") return false;
  return true;
}
var cachedManifest = null;
function loadManifest(prebuildDir) {
  if (cachedManifest?.dir === prebuildDir) {
    return cachedManifest.manifest;
  }
  const manifestPath = path.join(prebuildDir, "manifest.json");
  if (!fs.existsSync(manifestPath)) {
    return null;
  }
  try {
    const content = fs.readFileSync(manifestPath, "utf-8");
    const parsed = JSON.parse(content);
    if (!isPrebuildManifest(parsed)) return null;
    const manifest = parsed;
    cachedManifest = { manifest, dir: prebuildDir };
    return manifest;
  } catch {
    return null;
  }
}
function loadJsonFile(prebuildDir, relativePath) {
  const filePath = path.join(prebuildDir, relativePath);
  if (!fs.existsSync(filePath)) {
    return null;
  }
  try {
    const content = fs.readFileSync(filePath, "utf-8");
    return JSON.parse(content);
  } catch {
    return null;
  }
}
function isPrebuildExpired(manifest, maxAgeSec) {
  const ageMs = Date.now() - new Date(manifest.generatedAt).getTime();
  return ageMs > maxAgeSec * 1e3;
}
function getPrebuildAgeSec(manifest) {
  const ageMs = Date.now() - new Date(manifest.generatedAt).getTime();
  return Math.floor(ageMs / 1e3);
}
function canUsePrebuild() {
  if (typeof process === "undefined" || !process.versions?.node) {
    return false;
  }
  try {
    return typeof fs.existsSync === "function";
  } catch {
    return false;
  }
}
var PrebuildLoader = class {
  constructor(config) {
    this.prebuildDir = config.prebuildDir ?? DEFAULT_PREBUILD_DIR;
    this.maxPrebuildAgeSec = config.maxPrebuildAgeSec ?? DEFAULT_MAX_PREBUILD_AGE_SEC;
  }
  /**
   * Check if prebuild is available and not expired.
   */
  isAvailable() {
    if (!canUsePrebuild()) {
      return false;
    }
    const manifest = loadManifest(this.prebuildDir);
    if (!manifest) {
      return false;
    }
    return !isPrebuildExpired(manifest, this.maxPrebuildAgeSec);
  }
  /**
   * Load site data from prebuild cache.
   */
  loadSite(siteId) {
    const manifest = loadManifest(this.prebuildDir);
    if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
      return null;
    }
    const cacheFile = loadJsonFile(this.prebuildDir, "site.json");
    if (!cacheFile || cacheFile.data.site.id !== siteId) {
      return null;
    }
    return {
      data: cacheFile.data,
      prebuildAgeSec: getPrebuildAgeSec(manifest)
    };
  }
  /**
   * Load page data from prebuild cache.
   */
  loadPage(siteId, pagePath) {
    const manifest = loadManifest(this.prebuildDir);
    if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
      return null;
    }
    const cacheKey = `page:${siteId}:${pagePath}:false`;
    const relativePath = manifest.keyToFile[cacheKey];
    if (!relativePath) {
      return null;
    }
    const cacheFile = loadJsonFile(this.prebuildDir, relativePath);
    if (!cacheFile) {
      return null;
    }
    return {
      data: cacheFile.data,
      prebuildAgeSec: getPrebuildAgeSec(manifest)
    };
  }
  /**
   * Load entries from prebuild cache with runtime filtering.
   *
   * The prebuild stores ALL entries for each content type.
   * Filtering, ordering, and pagination are applied at runtime.
   */
  loadEntries(siteId, params) {
    if (params.preview) {
      return null;
    }
    if (params.mode === "manual" && params.entryIds?.length) {
      return null;
    }
    const manifest = loadManifest(this.prebuildDir);
    if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
      return null;
    }
    const cacheKey = `entries-all:${siteId}:${params.contentType}`;
    const relativePath = manifest.keyToFile[cacheKey];
    if (!relativePath) {
      return null;
    }
    const cacheFile = loadJsonFile(this.prebuildDir, relativePath);
    if (!cacheFile) {
      return null;
    }
    let entries = [...cacheFile.entries];
    if (params.order === "newest") {
      entries.sort((a, b) => {
        const aTime = a.publishedAt ? new Date(a.publishedAt).getTime() : 0;
        const bTime = b.publishedAt ? new Date(b.publishedAt).getTime() : 0;
        return bTime - aTime;
      });
    } else if (params.order === "oldest") {
      entries.sort((a, b) => {
        const aTime = a.publishedAt ? new Date(a.publishedAt).getTime() : 0;
        const bTime = b.publishedAt ? new Date(b.publishedAt).getTime() : 0;
        return aTime - bTime;
      });
    } else if (params.order === "title") {
      entries.sort((a, b) => (a.title || "").localeCompare(b.title || ""));
    }
    const total = entries.length;
    const offset = params.offset ?? 0;
    const limit = params.limit ?? 10;
    if (offset > 0) {
      entries = entries.slice(offset);
    }
    entries = entries.slice(0, limit);
    const prebuildAgeSec = getPrebuildAgeSec(manifest);
    if (params.includeMeta) {
      return {
        data: {
          entries,
          total,
          hasMore: offset + entries.length < total,
          limit,
          offset,
          totalPages: Math.ceil(total / limit),
          currentPage: Math.floor(offset / limit) + 1
        },
        prebuildAgeSec
      };
    }
    return {
      data: { entries },
      prebuildAgeSec
    };
  }
  /**
   * Load navigation data from prebuild cache.
   */
  loadNavigation() {
    const manifest = loadManifest(this.prebuildDir);
    if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
      return null;
    }
    const cacheFile = loadJsonFile(
      this.prebuildDir,
      "navigation/menus.json"
    );
    if (!cacheFile) {
      return null;
    }
    return {
      data: cacheFile.menus,
      prebuildAgeSec: getPrebuildAgeSec(manifest)
    };
  }
  /**
   * Load forms data from prebuild cache.
   */
  loadForms() {
    const manifest = loadManifest(this.prebuildDir);
    if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
      return null;
    }
    const cacheFile = loadJsonFile(
      this.prebuildDir,
      "forms/forms.json"
    );
    if (!cacheFile) {
      return null;
    }
    return {
      data: cacheFile.forms,
      prebuildAgeSec: getPrebuildAgeSec(manifest)
    };
  }
  /**
   * Get the manifest for inspection.
   */
  getManifest() {
    return loadManifest(this.prebuildDir);
  }
  /**
   * Clear the cached manifest (for testing).
   */
  clearCache() {
    cachedManifest = null;
  }
};
function createPrebuildLoader(config) {
  return new PrebuildLoader(config);
}
export {
  PrebuildLoader,
  canUsePrebuild,
  createPrebuildLoader
};
