#!/usr/bin/env node
// Publish seam: write a schema-valid blog post into src/content/blog/.
// This is what an IaC/CI step calls to turn an event into a post + a commit.
//
// Usage (flags):
//   node scripts/new-post.mjs --title "My post" --summary "..." \
//        --tags "kubernetes,gpu" [--date 2026-06-18] [--draft] \
//        [--slug custom-slug] [--body "markdown..."] [--bodyFile notes.md] [--force]
//
// Usage (event JSON — for pipelines):
//   node scripts/new-post.mjs --json '{"title":"...","summary":"...","tags":["x"],"body":"..."}'
//   cat event.json | node scripts/new-post.mjs --stdin
//
// Exits non-zero on invalid input so a malformed pipeline event fails the build.
import { parseArgs } from "node:util";
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
import { fileURLToPath } from "node:url";

const BLOG_DIR = fileURLToPath(new URL("../src/content/blog/", import.meta.url));

const { values } = parseArgs({
  options: {
    title: { type: "string" },
    summary: { type: "string" },
    tags: { type: "string" },
    date: { type: "string" },
    slug: { type: "string" },
    body: { type: "string" },
    bodyFile: { type: "string" },
    draft: { type: "boolean", default: false },
    force: { type: "boolean", default: false },
    json: { type: "string" },
    stdin: { type: "boolean", default: false },
  },
  allowPositionals: false,
});

function die(msg) {
  console.error(`new-post: ${msg}`);
  process.exit(1);
}

// --- Resolve the post fields from flags and/or a JSON event ----------------
let event = {};
if (values.stdin) {
  try {
    event = JSON.parse(readFileSync(0, "utf8"));
  } catch (e) {
    die(`could not parse JSON from stdin: ${e.message}`);
  }
} else if (values.json) {
  try {
    event = JSON.parse(values.json);
  } catch (e) {
    die(`could not parse --json: ${e.message}`);
  }
}

const title = values.title ?? event.title;
const summary = values.summary ?? event.summary;
const rawTags = values.tags ?? event.tags;
const date = values.date ?? event.date ?? new Date().toISOString().slice(0, 10);
const draft = values.draft || Boolean(event.draft);

let body = values.body ?? event.body;
if (values.bodyFile) body = readFileSync(values.bodyFile, "utf8");

// --- Validate (mirror the zod schema; fail fast) ---------------------------
if (!title || typeof title !== "string") die("a --title is required");
if (!summary || typeof summary !== "string") die("a --summary is required");
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) die(`date must be YYYY-MM-DD (got "${date}")`);

const tags = Array.isArray(rawTags)
  ? rawTags
  : typeof rawTags === "string"
    ? rawTags.split(",").map((t) => t.trim()).filter(Boolean)
    : [];

const slug =
  values.slug ??
  event.slug ??
  title
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .slice(0, 80);
if (!slug) die("could not derive a slug from the title; pass --slug");

// --- Compose the file ------------------------------------------------------
const yaml = (s) => JSON.stringify(String(s)); // safe double-quoted YAML scalar
const frontmatter = [
  "---",
  `title: ${yaml(title)}`,
  `date: ${date}`,
  `summary: ${yaml(summary)}`,
  `tags: [${tags.map(yaml).join(", ")}]`,
  `draft: ${draft}`,
  "---",
  "",
].join("\n");

const content =
  frontmatter +
  (body?.trim()
    ? `${body.trim()}\n`
    : `Write the post here.\n`);

mkdirSync(BLOG_DIR, { recursive: true });
const file = `${BLOG_DIR}${slug}.md`;
if (existsSync(file) && !values.force) {
  die(`${slug}.md already exists (use --force to overwrite)`);
}

writeFileSync(file, content, "utf8");
console.log(`wrote src/content/blog/${slug}.md${draft ? " (draft)" : ""}`);
