export interface ModelManifest {
  source: string;
  revision: string;
  architecture: string;
  labels: {
    toxic: number;
    nonToxic: number;
    names: Record<string, number>;
  };
  maxLength: number;
  quantization: string;
  runtime: string;
}

let manifestPromise: Promise<ModelManifest> | undefined;

export function loadModelManifest(modelBaseUrl: string): Promise<ModelManifest> {
  manifestPromise ??= fetch(`${modelBaseUrl}model-manifest.json`)
    .then((response) => {
      if (!response.ok) throw new Error(`VibeGuard model metadata unavailable (${response.status})`);
      return response.json() as Promise<ModelManifest>;
    })
    .then(validateManifest);
  return manifestPromise;
}

export function validateManifest(value: ModelManifest): ModelManifest {
  if (!value || typeof value.source !== "string" || typeof value.revision !== "string") throw new Error("Invalid VibeGuard model manifest");
  if (!Number.isInteger(value.labels?.toxic) || !Number.isInteger(value.labels?.nonToxic) || value.labels.toxic === value.labels.nonToxic || !value.labels?.names) throw new Error("Model manifest has no binary label mapping");
  if (!Number.isInteger(value.maxLength) || value.maxLength < 8) throw new Error("Model manifest has an invalid maximum length");
  return value;
}
