// TODO: add query string functionality to cache

const { ssrValidatePath } = require("../config")
const { log } = require("../lib/utils")
const { ssrRequest } = require("../lib/ssr-server.js")

;(function () {
    /** @type {HookResponse} */
    let response = null

    const request = context.request()
    let url = request.query("url")
    const noCache = request.query("noCache")

    // add sentry trace id to head
    const trace_id = context.debug.sentryTraceId()
    function addSentryTrace(content) {
        return content.replace("</head>", '<meta name="sentry-trace" content="' + trace_id + '" /></head>')
    }
    context.response.header("sentry-trace", trace_id)

    if (url) {
        // comment will be printed to html later
        let comment = ""
        /** @type {Date} */ // @ts-ignore
        context.ssrCacheValidUntil = null

        url = url.split("?")[0]
        comment += "url: " + url

        if (url && url.length > 1) {
            url = url.replace(/\/$/, "")
        }
        if (url == "/noindex" || !url) {
            url = "/" // see .htaccess
        }

        // check if url is in cache
        /** @type {Ssr[]} */ // @ts-ignore
        const cache =
            !noCache &&
            context.db.find("ssr", {
                filter: {
                    path: url,
                },
            })
        if (cache && cache.length) {
            // use cache
            context.response.header("X-SSR-Cache", "true")
            throw {
                status: 200,
                log: false,
                html: addSentryTrace(cache[0].content),
            }
        }

        // validate url
        let status = 200

        let pNorender = false
        let pNotfound = false

        const pR = ssrValidatePath(url)
        if (pR < 0) {
            pNotfound = true
        } else if (!pR) {
            pNorender = true
        }

        let head = ""
        let html = ""
        let error = ""

        comment += ", path: " + url

        let cacheIt = false
        if (pNorender) {
            html = "<!-- NO SSR RENDERING -->"
        } else if (pNotfound) {
            status = 404
            html = "404 NOT FOUND"
        } else {
            // @ts-ignore
            context.ssrCache = {}
            // @ts-ignore
            context.ssrRequest = ssrRequest

            // try rendering, if error output plain html
            try {
                // include App.svelte and render it
                // @ts-ignore

                // console.log("####### RENDERING ", url)
                const app = require("../lib/app.server")
                const rendered = app.default.render({
                    url: url,
                })
                head = rendered.head
                html = rendered.html

                // add ssrCache to head, cache is built in ssr.js/apiRequest
                head +=
                    "\n\n" +
                    "<script>window.__SSR_CACHE__ = " +
                    // @ts-ignore
                    JSON.stringify(context.ssrCache) +
                    "</script>"

                // status from webapp
                // @ts-ignore
                if (context.is404) {
                    // console.log("########## 404")
                    status = 404
                } else {
                    cacheIt = true
                }
            } catch (e) {
                // save error for later insert into html
                log(e.message)
                log(e.stack)
                error = "error: " + e.message + "\n\n" + e.stack
            }
        }

        // read html template and replace placeholders
        let tpl = context.fs.readFile("templates/spa.html")
        tpl = tpl.replace("<!--HEAD-->", head)
        tpl = tpl.replace("<!--HTML-->", html)
        tpl = tpl.replace("<!--SSR.ERROR-->", error ? "<!--" + error + "-->" : "")
        tpl = tpl.replace("<!--SSR.COMMENT-->", comment ? "<!--" + comment + "-->" : "")

        // save cache if adviced
        if (cacheIt && !noCache) {
            context.db.create("ssr", {
                // context.debug.dump("ssr", {
                path: url,
                content: tpl,
            })
        }

        // return html
        throw {
            status: status,
            log: false,
            html: addSentryTrace(tpl),
        }
    } else {
        // only admins are allowed to get without url parameter
        const auth = context.user.auth()
        if (!auth || auth.role !== 0) {
            throw {
                status: 403,
                message: "invalid auth",
                auth: auth,
            }
        }
    }
})()
