import { mkdirSync } from "node:fs"
import bunPluginTailwind from "bun-plugin-tailwind"
import { join, extname, dirname, basename, relative } from "node:path"

if (!import.meta.main) throw new Error("This script is intended to be run as a cli tool.")

type BuildRouteOptions = {
  distDir: string
  routeName: string
  filepath: string
}
/*
 * Builds dynamic routes in a separate process to avoid Bun.build corruption.
 * Running Bun.build in the same process as nanoRemix causes build failures after the first run.
 * Shelling out to this script isolates the build process and prevents this issue.
 */
const buildDynamicRoute = async ({ distDir, routeName, filepath }: BuildRouteOptions) => {
  const outDir = dirname(routeName)
  const filename = basename(routeName) + extname(filepath)
  const dynamicRouteFilepath = join(distDir, "routes", outDir, filename)
  await mkdirSync(dirname(dynamicRouteFilepath), { recursive: true })

  // Only import the Component so that tree-shaking will get rid of the server-side code
  const code = `
import Component from "${filepath}"
import { wrapComponentWithLoader} from "@workshop/nano-remix"
import { render } from 'hono/jsx/dom'

const root = document.getElementById('root')
const WrappedComponent = wrapComponentWithLoader(Component)
render(<WrappedComponent />, root)`

  await Bun.write(dynamicRouteFilepath, code)

  const result = await Bun.build({
    entrypoints: [dynamicRouteFilepath],
    outdir: join(distDir, outDir),
    sourcemap: "inline",
    target: "browser",
    format: "esm",
    plugins: [bunPluginTailwind],
  })

  if (!result.success) {
    throw new Error(`Build for "${routeName}" failed with exit code ${result.logs}.`)
  }

  return result
}

const args = process.argv.slice(2)

if (args.length < 3) {
  console.error("Usage: bun run scripts/build.ts <distDir> <routeName> <filepath>")
  process.exit(1)
}

const [distDir, routeName, filepath] = args as [string, string, string]

try {
  await buildDynamicRoute({ distDir, routeName, filepath })
} catch (error) {
  console.error(`❌ Build failed:`, error)
  process.exit(1)
}
