import { basename } from "node:path"
import { getPackageInfo } from "@workshop/shared/packages"

export const startSubdomainServers = async () => {
  const portMap: Record<string, number> = {}

  const packageInfo = await subdomainInfo()
  let currentPort = 3001

  const isDevMode = process.env.NODE_ENV !== "production"

  const processes = packageInfo.map((info) => {
    const port = currentPort++
    const dirname = basename(info.path)
    portMap[dirname] = port

    // Use subdomain:dev if available and in dev mode, otherwise use subdomain:start
    const script = isDevMode && info.hasDevScript ? "subdomain:dev" : "subdomain:start"

    return run(["bun", "run", script], {
      cwd: info.path,
      env: { PORT: port.toString() },
    })
  })

  Promise.all(processes).catch((err) => {
    console.log(`❌ Error starting subdomain servers:`, err)
    process.exit(1)
  })

  return portMap
}

export const subdomainInfo = async () => {
  const packageInfo = await getPackageInfo()
  const subdomainInfo = []
  for (const info of packageInfo) {
    if (!info.json) continue
    if (!info.json.scripts?.["subdomain:start"]) continue

    subdomainInfo.push({
      path: info.path,
      name: basename(info.path),
      hasDevScript: Boolean(info.json.scripts?.["subdomain:dev"]),
    })
  }

  return subdomainInfo
}

const run = async (cmd: string[], options: { cwd: string; env?: Record<string, string> }) => {
  const commandText = cmd.join(" ")
  const proc = Bun.spawn(cmd, {
    cwd: options.cwd,
    stdout: "inherit",
    stderr: "inherit",
    env: { ...process.env, ...options.env },
  })

  const status = await proc.exited

  if (status !== 0) {
    throw new Error(`Process "${commandText}" failed with exit code ${status}`)
  } else {
    console.log(`👋 Process ${commandText}(PID ${proc.pid}) exited with code ${status}`)
  }

  return status
}
