import { createReadStream, existsSync, statSync } from 'node:fs'
import { createServer } from 'node:http'
import { extname, resolve, sep } from 'node:path'
import { fileURLToPath } from 'node:url'
import { handleApiRequest } from './game-api.mjs'

process.env.NODE_ENV = 'production'

const distPath = fileURLToPath(new URL('../dist', import.meta.url))
const indexPath = resolve(distPath, 'index.html')
const host = process.env.HOST ?? '127.0.0.1'
const port = Number(process.env.PORT ?? 4173)
const contentTypes = {
  '.css': 'text/css; charset=utf-8',
  '.html': 'text/html; charset=utf-8',
  '.ico': 'image/x-icon',
  '.jpeg': 'image/jpeg',
  '.jpg': 'image/jpeg',
  '.js': 'text/javascript; charset=utf-8',
  '.json': 'application/json; charset=utf-8',
  '.png': 'image/png',
  '.svg': 'image/svg+xml',
  '.webp': 'image/webp',
}

function sendFile(response, filePath) {
  response.statusCode = 200
  response.setHeader(
    'Content-Type',
    contentTypes[extname(filePath).toLowerCase()] ?? 'application/octet-stream',
  )
  response.setHeader('X-Content-Type-Options', 'nosniff')
  response.setHeader('Referrer-Policy', 'same-origin')
  response.setHeader('X-Frame-Options', 'DENY')
  createReadStream(filePath).pipe(response)
}

async function serveStatic(request, response) {
  const requestPath = decodeURIComponent(new URL(request.url, 'http://localhost').pathname)
  const candidate = resolve(distPath, `.${requestPath}`)
  const insideDist = candidate === distPath || candidate.startsWith(`${distPath}${sep}`)

  if (requestPath === '/admin.html') {
    response.statusCode = 404
    response.end('Not found')
    return
  }

  if (
    insideDist
    && existsSync(candidate)
    && statSync(candidate).isFile()
  ) {
    sendFile(response, candidate)
    return
  }

  if (!existsSync(indexPath)) {
    response.statusCode = 503
    response.end('Build missing. Run npm run build.')
    return
  }
  sendFile(response, indexPath)
}

const server = createServer((request, response) => {
  handleApiRequest(request, response, () => {
    serveStatic(request, response).catch(() => {
      response.statusCode = 500
      response.end('Unable to serve the application.')
    })
  })
})

server.listen(port, host, () => {
  console.log(`I want to Heal listening on http://${host}:${port}`)
})
