#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { computeBaseConfigSchemaResponse } from "../src/config/schema-base.js";
import { formatGeneratedModule } from "./lib/format-generated-module.mjs";

const GENERATED_BY = "scripts/generate-base-config-schema.ts";
const DEFAULT_OUTPUT_PATH = "src/config/schema.base.generated.ts";
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");

function readIfExists(filePath: string): string | null {
  try {
    return fs.readFileSync(filePath, "utf8");
  } catch {
    return null;
  }
}

function formatTypeScriptModule(source: string, outputPath: string): string {
  return formatGeneratedModule(source, {
    repoRoot: REPO_ROOT,
    outputPath,
    errorLabel: "base config schema",
  });
}

export function renderBaseConfigSchemaModule(params?: { generatedAt?: string }): string {
  const payload = computeBaseConfigSchemaResponse({
    generatedAt: params?.generatedAt ?? new Date().toISOString(),
  });
  return formatTypeScriptModule(
    `// Auto-generated by ${GENERATED_BY}. Do not edit directly.

import type { BaseConfigSchemaResponse } from "./schema-base.js";

export const GENERATED_BASE_CONFIG_SCHEMA = ${JSON.stringify(payload, null, 2)} as const satisfies BaseConfigSchemaResponse;
`,
    DEFAULT_OUTPUT_PATH,
  );
}

export function writeBaseConfigSchemaModule(params?: {
  repoRoot?: string;
  outputPath?: string;
  check?: boolean;
}): { changed: boolean; wrote: boolean; outputPath: string } {
  const repoRoot = path.resolve(params?.repoRoot ?? REPO_ROOT);
  const outputPath = path.resolve(repoRoot, params?.outputPath ?? DEFAULT_OUTPUT_PATH);
  const current = readIfExists(outputPath);
  const generatedAt =
    current?.match(/generatedAt:\s*"([^"]+)"/u)?.[1] ??
    current?.match(/"generatedAt":\s*"([^"]+)"/u)?.[1] ??
    new Date().toISOString();
  const next = renderBaseConfigSchemaModule({ generatedAt });
  const changed = current !== next;

  if (params?.check) {
    return { changed, wrote: false, outputPath };
  }

  if (changed) {
    fs.writeFileSync(outputPath, next, "utf8");
  }
  return { changed, wrote: changed, outputPath };
}

const args = new Set(process.argv.slice(2));
if (args.has("--check") && args.has("--write")) {
  throw new Error("Use either --check or --write, not both.");
}

if (import.meta.url === new URL(process.argv[1] ?? "", "file://").href) {
  const result = writeBaseConfigSchemaModule({ check: args.has("--check") });
  if (result.changed) {
    if (args.has("--check")) {
      console.error(
        `[base-config-schema] stale generated output at ${path.relative(process.cwd(), result.outputPath)}`,
      );
      process.exitCode = 1;
    } else {
      console.log(`[base-config-schema] wrote ${path.relative(process.cwd(), result.outputPath)}`);
    }
  }
}
