import express from 'express'
import puppeteer from 'puppeteer'

const captureUrl = process.env.CAPTURE_URL || 'http://host.docker.internal:3000/'
const port = process.env.PORT || 5678
const maxPages = process.env.MAX_PAGES || 5
const timeout = process.env.TIMEOUT || 10000
const cache = process.env.CACHE || 60000
const width = process.env.WIDTH || 600
const height = process.env.HEIGHT || 315
const deviceScaleFactor = process.env.SCALE_FACTOR || 2

let browser
const app = express()

app.get('/health', (req, res) => {
  res.status(200).end()
})

app.get('/*', async (req, res) => {
  browser ||= await puppeteer.launch({
    headless: 'new',
    executablePath: 'google-chrome-stable',
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  })
  const url = new URL(req.originalUrl, captureUrl)
  console.time(url.href)
  console.timeLog(url.href, 'capturing', 'current pages', (await browser.pages()).length)

  // limit number of active pages
  if ((await browser.pages()).length > maxPages + 1) {
    console.timeLog(url.href, 'too many pages')
    console.timeEnd(url.href)
    return res.writeHead(503, {
      'Retry-After': 1
    }).end()
  }

  let page
  try {
    page = await browser.newPage()
    await page.setViewport({ width, height, deviceScaleFactor })
    await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }])
    await page.goto(url.href, { waitUntil: 'load', timeout })
    const file = await page.screenshot({ type: 'png', captureBeyondViewport: false })
    res.setHeader('Content-Type', 'image/png')
    res.setHeader('Cache-Control', `public, max-age=${cache}, immutable`)
    res.status(200).end(file)
  } catch (err) {
    console.log(err)
    return res.status(500).end()
  } finally {
    console.timeEnd(url.href)
    page?.close()
  }
})

app.listen(port, () =>
  console.log(`Screenshot listen on http://:${port}`)
)