/**
 * Pipeline : PNG source → découpes (sharp) → SVG (VTracer CLI).
 *
 * Prérequis : `cargo install vtracer` ou binaire sur PATH / variable VTRACER_PATH.
 * Source attendue : public/brand/ultimail-original.png (sinon public/brand/utlimail-original.png).
 */
import { execFileSync } from "node:child_process"
import { existsSync, copyFileSync } from "node:fs"
import { mkdirSync, mkdtempSync, rmSync } from "node:fs"
import { tmpdir } from "node:os"
import { join, dirname } from "node:path"
import { fileURLToPath } from "node:url"
import sharp from "sharp"

const __dirname = dirname(fileURLToPath(import.meta.url))
const root = join(__dirname, "..")
const brandDir = join(root, "public/brand")

const VT_ARGS_BALANCED = [
  "--mode",
  "spline",
  "--filter_speckle",
  "5",
  "--gradient_step",
  "11",
  "--color_precision",
  "6",
  "--path_precision",
  "2",
]

const VT_ARGS_MARK = [
  "--mode",
  "spline",
  "--filter_speckle",
  "6",
  "--gradient_step",
  "12",
  "--color_precision",
  "5",
  "--path_precision",
  "2",
]

function findSourcePng() {
  const a = join(brandDir, "ultimail-original.png")
  const b = join(brandDir, "utlimail-original.png")
  if (existsSync(a)) return a
  if (existsSync(b)) return b
  throw new Error(
    "Missing public/brand/ultimail-original.png (or legacy utlimail-original.png). Drop the logo PNG there."
  )
}

function findVtracer() {
  if (process.env.VTRACER_PATH && existsSync(process.env.VTRACER_PATH)) {
    return process.env.VTRACER_PATH
  }
  const home = process.env.HOME || ""
  const fromCargo = join(home, ".cargo/bin/vtracer")
  if (existsSync(fromCargo)) return fromCargo
  try {
    const p = execFileSync("command", ["-v", "vtracer"], { encoding: "utf8" }).trim().split("\n")[0]
    if (p) return p
  } catch {
    /* ignore */
  }
  throw new Error(
    "vtracer not found. Install: cargo install vtracer --version 0.6.5  OR set VTRACER_PATH to the binary."
  )
}

function vtracer(bin, inputPng, outputSvg, extraCliArgs) {
  execFileSync(bin, ["--input", inputPng, "--output", outputSvg, ...extraCliArgs], {
    stdio: "inherit",
  })
}

async function main() {
  mkdirSync(brandDir, { recursive: true })
  const src = findSourcePng()
  const canonical = join(brandDir, "ultimail-original.png")
  if (src !== canonical) {
    copyFileSync(src, canonical)
  }

  const vbin = findVtracer()
  const tmp = mkdtempSync(join(tmpdir(), "um-vec-"))
  try {
    const base = sharp(canonical)
    const meta = await base.metadata()
    const W = meta.width ?? 0
    const H = meta.height ?? 0
    if (!W || !H) throw new Error("Could not read image dimensions")

    const splitY = Math.min(H - 40, Math.max(80, Math.round(H * 0.52)))

    const topStrip = join(tmp, "strip-icon.png")
    const botStrip = join(tmp, "strip-text.png")
    await base.clone().extract({ left: 0, top: 0, width: W, height: splitY }).png().toFile(topStrip)
    await base.clone().extract({ left: 0, top: splitY, width: W, height: H - splitY }).png().toFile(botStrip)

    const side = Math.min(W, splitY)
    const left = Math.max(0, Math.floor((W - side) / 2))
    const topCrop = Math.max(0, Math.floor((splitY - side) / 2))
    const markSrc = join(tmp, "mark-square-src.png")
    await sharp(topStrip)
      .extract({ left, top: topCrop, width: side, height: side })
      .resize(512, 512, {
        fit: "contain",
        position: "center",
        background: { r: 255, g: 255, b: 255, alpha: 1 },
      })
      .flatten({ background: "#ffffff" })
      .png()
      .toFile(markSrc)

    const iconH = 240
    const textH = 160
    const iconBuf = await sharp(topStrip)
      .resize({ height: iconH, fit: "inside" })
      .flatten({ background: "#ffffff" })
      .toBuffer()
    const textBuf = await sharp(botStrip)
      .resize({ height: textH, fit: "inside" })
      .flatten({ background: "#ffffff" })
      .toBuffer()

    const iw = (await sharp(iconBuf).metadata()).width ?? 0
    const ih = (await sharp(iconBuf).metadata()).height ?? 0
    const tw = (await sharp(textBuf).metadata()).width ?? 0
    const th = (await sharp(textBuf).metadata()).height ?? 0
    const padX = 48
    const gap = 56
    const canvasW = iw + tw + padX * 2 + gap
    const canvasH = Math.max(ih, th) + 32
    const horizRaster = join(tmp, "horizontal-layout.png")
    await sharp({
      create: {
        width: canvasW,
        height: canvasH,
        channels: 3,
        background: { r: 255, g: 255, b: 255 },
      },
    })
      .composite([
        { input: iconBuf, left: padX, top: Math.round((canvasH - ih) / 2) },
        { input: textBuf, left: padX + iw + gap, top: Math.round((canvasH - th) / 2) },
      ])
      .png()
      .toFile(horizRaster)

    const stackedSvg = join(brandDir, "ultimail-wordmark-stacked.svg")
    const horizontalSvg = join(brandDir, "ultimail-wordmark-horizontal.svg")
    const markSvgTmp = join(tmp, "mark.svg")

    console.log("VTracer: full stacked logo…")
    vtracer(vbin, canonical, stackedSvg, VT_ARGS_BALANCED)

    console.log("VTracer: horizontal composite…")
    vtracer(vbin, horizRaster, horizontalSvg, VT_ARGS_BALANCED)

    console.log("VTracer: icon mark (square)…")
    vtracer(vbin, markSrc, markSvgTmp, VT_ARGS_MARK)

    const publicMark = join(root, "public/ultimail-mark.svg")
    copyFileSync(markSvgTmp, publicMark)

    console.log("Header icon + favicons (raster transparent)…")
    execFileSync(process.execPath, [join(__dirname, "emit-ultimail-header-icon.mjs")], {
      cwd: root,
      stdio: "inherit",
    })

    console.log("Done:", { stackedSvg, horizontalSvg, publicMark })
  } finally {
    rmSync(tmp, { recursive: true, force: true })
  }
}

main().catch((e) => {
  console.error(e)
  process.exit(1)
})
