import { describe, test, expect, beforeAll, afterAll } from "vitest"
import { existsSync, readFileSync, rmSync, mkdirSync, writeFileSync, mkdtempSync } from "node:fs"
import path from "node:path"
import os from "node:os"
import { fileURLToPath } from "node:url"
import { spawnSync } from "node:child_process"
import { loadBrand } from "../src/config"
import { buildSvg, computeHash } from "../src/render"
import { loadFixture } from "./helpers/fixtures"

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const DRAW_IMAGE_DIR = path.resolve(__dirname, "..")
const TMP = path.join(os.tmpdir(), `draw-image-integration-${process.pid}`)

beforeAll(() => {
  if (existsSync(TMP)) rmSync(TMP, { recursive: true, force: true })
  mkdirSync(TMP, { recursive: true })
})

afterAll(() => {
  if (existsSync(TMP)) rmSync(TMP, { recursive: true, force: true })
})

function renderToPng(svg: string, outPath: string): void {
  const tmpDir = mkdtempSync(path.join(os.tmpdir(), `draw-image-test-${process.pid}-`))
  const tmpSvg = path.join(tmpDir, "input.svg")
  try {
    writeFileSync(tmpSvg, svg)
    const r = spawnSync("node", [path.join(DRAW_IMAGE_DIR, "render.mjs"), tmpSvg, outPath], {
      encoding: "utf-8",
    })
    if (r.status !== 0) throw new Error(`render.mjs failed: ${r.stderr || r.stdout}`)
  } finally {
    if (existsSync(tmpDir)) rmSync(tmpDir, { recursive: true, force: true })
  }
}

describe("integration — render pipeline", () => {
  test("renders valid PNG 1024x1024", () => {
    const brand = loadBrand(DRAW_IMAGE_DIR)
    const templateSvg = loadFixture("cover")
    const args = { template: "cover", title: "Test", out: path.join(TMP, "cover.png") }
    const hash = computeHash(brand, templateSvg, args)
    const svg = buildSvg(templateSvg, brand, args, DRAW_IMAGE_DIR)

    const outPath = path.join(TMP, "cover.png")
    renderToPng(svg, outPath)

    expect(existsSync(outPath)).toBe(true)
    const buf = readFileSync(outPath)
    expect(buf[0]).toBe(0x89)
    expect(buf[1]).toBe(0x50)
    expect(buf[2]).toBe(0x4e)
    expect(buf[3]).toBe(0x47)
    const width = buf.readUInt32BE(16)
    const height = buf.readUInt32BE(20)
    expect(width, `PNG width should be 1024, got ${width}`).toBe(1024)
    expect(height, `PNG height should be 1024, got ${height}`).toBe(1024)

    expect(hash).toHaveLength(64)
  })

  test("creates output directory recursively", () => {
    const brand = loadBrand(DRAW_IMAGE_DIR)
    const templateSvg = loadFixture("cover")
    const args = { template: "cover", title: "Deep", out: path.join(TMP, "a", "b", "c", "cover.png") }
    const svg = buildSvg(templateSvg, brand, args, DRAW_IMAGE_DIR)
    const outPath = path.join(TMP, "a", "b", "c", "cover.png")
    renderToPng(svg, outPath)
    expect(existsSync(outPath)).toBe(true)
  })
})