import { writeFileSync, mkdirSync, existsSync, readFileSync, rmSync } from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import os from "node:os"
import { spawnSync } from "node:child_process"
import { loadBrand } from "./src/config.ts"
import { loadTemplate, buildSvg, computeHash } from "./src/render.ts"

const __dirname = path.dirname(fileURLToPath(import.meta.url))

function parseArgs(argv: string[]): Record<string, string> {
  const out: Record<string, string> = {}
  for (let i = 0; i < argv.length; i++) {
    const a = argv[i]
    if (a.startsWith("--")) {
      const key = a.slice(2)
      const val = argv[i + 1] ?? ""
      out[key] = val
      i++
    }
  }
  return out
}

function main() {
  const argv = process.argv.slice(2)
  if (argv.length < 2 || argv[0] !== "render") {
    process.stderr.write('usage: node cli.ts render <template> --title "..." [--slots icon=mic] [--subtitle text] [--out path] [--template-dir dir]\n')
    process.exit(2)
  }

  const template = argv[1]
  const opts = parseArgs(argv.slice(2))
  const title = opts.title ?? ""
  const subtitle = opts.subtitle
  const out = opts.out ?? "./assets/cover.png"
  const templateDir = opts["template-dir"]

  const slots: Record<string, string> = {}
  if (opts.slots) {
    for (const pair of opts.slots.split(",")) {
      const eq = pair.indexOf("=")
      if (eq !== -1) slots[pair.slice(0, eq).trim()] = pair.slice(eq + 1).trim()
    }
  }

  const brand = loadBrand(__dirname)
  const templateSvg = loadTemplate(__dirname, template, templateDir)
  const hash = computeHash(brand, templateSvg, { template, title, subtitle, slots, out })

  const outResolved = path.resolve(out)
  const metaPath = outResolved.replace(/\.png$/, ".meta.json")
  if (existsSync(outResolved) && existsSync(metaPath)) {
    try {
      const meta = JSON.parse(readFileSync(metaPath, "utf-8"))
      if (meta.hash === hash) {
        console.log(JSON.stringify({ path: outResolved, hash, status: "skipped" }))
        return
      }
    } catch {
      // stale meta, re-render
    }
  }

  const svg = buildSvg(templateSvg, brand, { template, title, subtitle, slots, out }, __dirname)
  const tmpSvg = path.join(os.tmpdir(), `draw-image-${process.pid}.svg`)

  try {
    writeFileSync(tmpSvg, svg)

    const r = spawnSync("node", [path.join(__dirname, "render.mjs"), tmpSvg, outResolved], {
      encoding: "utf-8",
    })
    if (r.status !== 0) {
      process.stderr.write(r.stderr || r.stdout || "render failed\n")
      process.exit(1)
    }

    const meta = {
      hash,
      generatedAt: new Date().toISOString(),
      size: 1024,
    }
    writeFileSync(metaPath, JSON.stringify(meta, null, 2) + "\n")
    console.log(JSON.stringify({ path: outResolved, hash, status: "rendered" }))
  } finally {
    if (existsSync(tmpSvg)) rmSync(tmpSvg, { force: true })
  }
}

main()