#!/usr/bin/env node
/**
 * exxat-ui add-product <Suffix> [--color oklch(...)]
 *
 * Writes public/tenant-products.json (merge) + product scaffold files into cwd.
 */

import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"
import { dirname, resolve } from "path"
import { fileURLToPath, pathToFileURL } from "url"

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

function slugFromSuffix(suffix) {
  return (
    suffix
      .trim()
      .toLowerCase()
      .replace(/[^a-z0-9]+/g, "-")
      .replace(/^-+|-+$/g, "") || "custom-product"
  )
}

function pascalFromSlug(slug) {
  return slug
    .split("-")
    .filter(Boolean)
    .map(p => p.charAt(0).toUpperCase() + p.slice(1))
    .join("")
}

async function loadTenantProductsModule() {
  const modPath = resolve(__dirname, "../dist/product-framework/tenant-products/index.js")
  if (!existsSync(modPath)) {
    console.error(
      "tenant-products not built — run `pnpm --filter @exxatdesignux/ui build` in the DS workspace first.",
    )
    process.exit(1)
  }
  return import(pathToFileURL(modPath).href)
}

function parseArgs(argv) {
  const positional = []
  let color = "oklch(0.62 0.20 200)"
  for (let i = 0; i < argv.length; i++) {
    const arg = argv[i]
    if (arg === "--color" && argv[i + 1]) {
      color = argv[++i]
      continue
    }
    if (!arg.startsWith("-")) positional.push(arg)
  }
  const suffix = positional[0]
  if (!suffix?.trim()) {
    console.error("Usage: exxat-ui add-product <Suffix> [--color oklch(...)]\n")
    console.error("Example: exxat-ui add-product Assessment --color oklch(0.658 0.147 43)")
    process.exit(1)
  }
  return { suffix: suffix.trim(), color: color.trim() }
}

function mergeCatalogFile(cwd, record, buildShippedTenantCatalogFile, serializeShippedTenantCatalogFile) {
  const publicPath = resolve(cwd, "public/tenant-products.json")
  let existingProductData
  if (existsSync(publicPath)) {
    try {
      const parsed = JSON.parse(readFileSync(publicPath, "utf8"))
      existingProductData = parsed.productData
    } catch {
      console.warn("Could not parse existing tenant-products.json — replacing file")
    }
  } else {
    mkdirSync(resolve(cwd, "public"), { recursive: true })
  }

  const file = buildShippedTenantCatalogFile([record])
  if (existingProductData && typeof existingProductData === "object") {
    file.productData = { ...existingProductData, ...file.productData }
  }
  writeFileSync(publicPath, serializeShippedTenantCatalogFile(file), "utf8")
  console.log(`Wrote ${publicPath}`)
}

export async function runAddProduct(argv = process.argv.slice(2)) {
  const { suffix, color } = parseArgs(argv)
  const {
    brandToTenantRecord,
    buildShippedTenantCatalogFile,
    generateProductScaffold,
    serializeShippedTenantCatalogFile,
  } = await loadTenantProductsModule()

  const record = brandToTenantRecord({ suffix, brandColor: color })

  const cwd = process.cwd()
  mergeCatalogFile(
    cwd,
    record,
    buildShippedTenantCatalogFile,
    serializeShippedTenantCatalogFile,
  )

  const { files, instructions } = generateProductScaffold(record)
  for (const file of files) {
    if (file.path === "public/tenant-products.json") continue
    const out = resolve(cwd, file.path)
    mkdirSync(dirname(out), { recursive: true })
    writeFileSync(out, file.content, "utf8")
    console.log(`Wrote ${file.path}`)
  }

  const pascal = pascalFromSlug(record.slug)
  console.log(`\n${pascal} product scaffold complete.\n`)
  for (const line of instructions) {
    console.log(`  • ${line}`)
  }
}

if (import.meta.url === pathToFileURL(process.argv[1]).href) {
  runAddProduct(process.argv.slice(2)).catch(err => {
    console.error(err)
    process.exit(1)
  })
}
