/**
 * Fetches the OpenAPI spec from the running stemedb-api server
 * and saves it to public/openapi.json for use by Scalar.
 *
 * Usage:
 *   npx tsx scripts/fetch-openapi.ts
 *
 * Set STEMEDB_API_URL to override the default endpoint.
 */

import { writeFileSync, existsSync, readFileSync } from "fs";
import { join } from "path";

const API_URL = process.env.STEMEDB_API_URL || "http://127.0.0.1:18180";
const OPENAPI_ENDPOINT = `${API_URL}/api-docs/openapi.json`;
const OUTPUT_PATH = join(process.cwd(), "public", "openapi.json");

async function fetchOpenApiSpec(): Promise<void> {
  console.log(`Fetching OpenAPI spec from ${OPENAPI_ENDPOINT}...`);

  try {
    const response = await fetch(OPENAPI_ENDPOINT);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const spec = await response.json();

    // Validate it looks like an OpenAPI spec
    if (!spec.openapi || !spec.info || !spec.paths) {
      throw new Error("Invalid OpenAPI spec: missing required fields");
    }

    writeFileSync(OUTPUT_PATH, JSON.stringify(spec, null, 2));
    console.log(`OpenAPI spec saved to ${OUTPUT_PATH}`);
    console.log(`  Version: ${spec.info.version}`);
    console.log(`  Title: ${spec.info.title}`);
    console.log(`  Endpoints: ${Object.keys(spec.paths).length}`);
  } catch (error) {
    if (error instanceof Error && error.message.includes("ECONNREFUSED")) {
      console.warn("Could not connect to stemedb-api server.");
      console.warn("Using existing spec if available, or provide a bundled fallback.");

      if (existsSync(OUTPUT_PATH)) {
        const existing = JSON.parse(readFileSync(OUTPUT_PATH, "utf-8"));
        console.log(`Using cached spec (v${existing.info?.version || "unknown"})`);
        return;
      }

      console.error("No cached spec available. Start stemedb-api and retry.");
      process.exit(1);
    }

    console.error("Failed to fetch OpenAPI spec:", error);
    process.exit(1);
  }
}

fetchOpenApiSpec();
