import { renderServer } from "./renderServer"
import { buildRoute } from "./buildRoute"
import { join, extname } from "node:path"
import { stat } from "node:fs/promises"

type Options = {
  routesDir?: string
  distDir?: string
  publicDir?: string
}

let defaultPublicDir: string | undefined
try {
  const publicDir = join(process.cwd(), "public")
  const statInfo = await stat(publicDir)
  if (statInfo.isDirectory()) {
    defaultPublicDir = publicDir
  }
} catch (error) {}

export const nanoRemix = async (req: Request, options: Options = {}) => {
  const defaultRoutesDir = join(process.cwd(), "src", "routes")
  const nanoRemixDir = join(process.cwd(), ".nano-remix")
  const defaultDistDir = join(nanoRemixDir, "dist")
  const publicDir = options.publicDir || defaultPublicDir
  const url = new URL(req.url)

  if (publicDir) {
    const filePath = join(publicDir, url.pathname)
    const file = Bun.file(filePath)
    if (await file.exists()) {
      return new Response(file)
    }
  }

  const routesDir = options.routesDir || defaultRoutesDir
  const distDir = options.distDir || defaultDistDir
  const router = new Bun.FileSystemRouter({ style: "nextjs", dir: routesDir })

  // I want to request the css and js files directly, so we detect the extension
  const ext = extname(url.pathname)
  const basename = ext ? url.pathname.slice(0, -ext.length) : url.pathname
  const route = router.match(basename)

  if (!route) {
    return new Response("Route Not Found", {
      status: 404,
      headers: { "Content-Type": "text/plain" },
    })
  }

  const routeName = route.name === "/" ? "/index" : route.name

  // If the the route includes an extension it is a static file that we serve from the distDir
  if (!ext) {
    await buildRoute({ distDir, routeName, filepath: route.filePath })
    return await renderServer(req, route)
  } else {
    const file = Bun.file(join(distDir, routeName + ext))

    if (!(await file.exists())) {
      return new Response("File Not Found", {
        status: 404,
        headers: { "Content-Type": "text/plain" },
      })
    }
    return new Response(file)
  }
}
