import { Browser, launch } from 'puppeteer'

let browserPromise: Promise<Browser> | null = null

function getBrowser() {
  if (!browserPromise) {
    browserPromise = launch({
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    })
  }
  return browserPromise
}

/**
 * Closes the Puppeteer browser instance if it exists.
 * This function is useful for cleaning up resources when the application is shutting down or when the browser is no longer needed.
 */
export async function closeMermaidBrowser() {
  if (browserPromise) {
    const browser = await browserPromise
    await browser.close()
    browserPromise = null
  }
}

const cache = new Map<string, string>()

/**
 * Renders a Mermaid chart to SVG using Puppeteer and caches the result.
 * @param chart - The Mermaid chart definition as a string.
 * @returns A promise that resolves to the rendered SVG string.
 */
export async function renderMermaidToSvg(chart: string): Promise<string> {
  const cached = cache.get(chart)
  if (cached) return cached

  const browser = await getBrowser()
  const page = await browser.newPage()

  try {
    await page.setContent(`
      <!DOCTYPE html>
      <html><body><div id="target"></div></body></html>
    `)
    await page.addScriptTag({
      url: 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js',
    })

    const svg = await page.evaluate(async (source) => {
      // @ts-expect-error mermaid is loaded globally via the script tag above
      window.mermaid.initialize({ startOnLoad: false, theme: 'neutral' })
      // @ts-expect-error same as above
      const { svg: renderedSvg } = await window.mermaid.render('mermaid-diagram', source)
      return renderedSvg
    }, chart)

    cache.set(chart, svg)
    return svg
  } finally {
    await page.close()
  }
}
