/**
 * Imports a blog export file (categories, authors, articles, FAQs) into this
 * CMS. The same import the admin's Blogs → Import JSON screen runs.
 *
 *   npm run import:json -- wordpress-import/blog-export.json --dry-run
 *   npm run import:json -- wordpress-import/blog-export.json
 *   npm run import:json -- wordpress-import/blog-export.json --update
 *   npm run import:json -- blog-export.json --report wordpress-import/json-import-report.json
 *
 * Articles whose slug already exists are skipped unless --update is given,
 * so the import can be re-run safely. Images are never downloaded; see
 * src/features/blog-import/service.ts. The format is in
 * src/features/blog-import/format.ts and docs/blog-export-format.md.
 */
import "dotenv/config";

import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import { parseArgs } from "node:util";

import {
  importBlogExport,
  parseBlogExport,
} from "@/features/blog-import/service";
import { db } from "@/lib/db";
import { notifySite } from "@/lib/site";

const { values: args, positionals } = parseArgs({
  allowPositionals: true,
  options: {
    "dry-run": { type: "boolean", default: false },
    update: { type: "boolean", default: false },
    report: { type: "string" },
  },
});

async function main() {
  const filePath = positionals[0];
  if (!filePath) {
    throw new Error(
      "Usage: npm run import:json -- <file.json> [--dry-run] [--update] [--report out.json]",
    );
  }

  const parsed = parseBlogExport(
    await readFile(path.resolve(filePath), "utf8"),
  );
  if (!parsed.ok) {
    console.error(parsed.error);
    for (const issue of parsed.issues) console.error(`  ${issue}`);
    process.exitCode = 1;
    return;
  }

  const dryRun = args["dry-run"];
  console.log(
    `${dryRun ? "Dry run: nothing will be written. " : ""}Importing ${parsed.data.posts.length} posts from ${filePath}` +
      ` (existing articles: ${args.update ? "updated" : "skipped"}).`,
  );

  const result = await importBlogExport(parsed.data, {
    existing: args.update ? "update" : "skip",
    dryRun,
    userId: null,
  });

  console.log("");
  for (const post of result.posts) {
    const mark =
      post.action === "fail" ? "✗" : post.warnings.length ? "!" : "✓";
    const verb =
      dryRun && (post.action === "create" || post.action === "update")
        ? `would ${post.action}`
        : post.action;
    console.log(
      `${mark} ${verb.padEnd(14)} ${post.slug}${post.reason ? `  (${post.reason})` : ""}`,
    );
    for (const warning of post.warnings) console.log(`      ${warning}`);
  }
  if (result.notes.length) console.log("");
  for (const note of result.notes) console.log(note);
  console.log("");
  console.log(JSON.stringify(result.summary, null, 2));

  if (args.report) {
    const target = path.resolve(args.report);
    await mkdir(path.dirname(target), { recursive: true });
    await writeFile(target, JSON.stringify(result, null, 2) + "\n");
    console.log(`\nReport: ${target}`);
  }

  if (!dryRun && result.liveSlugs.length) {
    await notifySite(result.liveSlugs);
  }
  if (result.summary.fail) process.exitCode = 1;
}

main()
  .catch((error) => {
    console.error(error instanceof Error ? error.message : String(error));
    process.exitCode = 1;
  })
  .finally(() => db.$disconnect());
