const { ssrValidatePath, ssrAllowedAPIEndpoints } = require("../config")

const { obj2str, log } = require("../lib/utils")
;(function () {
    /** @type {HookResponse} */
    var response = null

    var request = context.request()
    var url = request.query("url")
    var noCache = request.query("noCache")

    // add sentry trace id to head
    var 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
        var comment = ""

        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
        var cache =
            !noCache &&
            context.db.find("ssr", {
                filter: {
                    path: url,
                },
            })
        if (cache && cache.length) {
            // use cache
            throw {
                status: 200,
                log: false,
                html: addSentryTrace(cache[0].content),
            }
        }

        // validate url
        var status = 200

        var pNorender = false
        var pNotfound = false

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

        var head = ""
        var html = ""
        var error = ""

        comment += ", path: " + url

        var cacheIt = false
        if (pNorender) {
            html = "<!-- NO SSR RENDERING -->"
        } else if (pNotfound) {
            status = 404
            html = "404 NOT FOUND"
        } else {
            // try rendering, if error output plain html
            try {
                // @ts-ignore
                context.ssrCache = {}
                // @ts-ignore
                context.ssrFetch = function (endpoint, options) {
                    var data
                    if (ssrAllowedAPIEndpoints.indexOf(endpoint) > -1) {
                        var _options = Object.assign({}, options)

                        if (_options.sort) _options.sort = [_options.sort]

                        try {
                            /*console.log(
                                "SSR",
                                endpoint,
                                JSON.stringify(_options)
                            )*/
                            var goSlice = context.db.find(endpoint, _options || {})
                            // need to deep copy, so shift and delete on pure js is possible
                            data = JSON.parse(JSON.stringify(goSlice))
                        } catch (e) {
                            console.log("ERROR", JSON.stringify(e))
                            data = []
                        }
                    } else {
                        console.log("SSR forbidden", endpoint)
                        data = []
                    }

                    var count = (data && data.length) || 0
                    if (options && count == options.limit) {
                        // read count from db
                        count = context.db.count(endpoint, _options || {})
                    }
                    var r = { data: data, count: count }

                    // @ts-ignore
                    context.ssrCache[obj2str({ endpoint: endpoint, options: options })] = r

                    return r
                }

                // include App.svelte and render it
                // @ts-ignore
                var app = require("../lib/app.server")
                var rendered = app.default.render({
                    url: url,
                })
                head = rendered.head
                html = rendered.html

                // add ssrCache to head
                head +=
                    "\n\n" +
                    "<script>window.__SSR_CACHE__ = " +
                    // @ts-ignore
                    JSON.stringify(context.ssrCache) +
                    "</script>"

                // status from webapp
                // @ts-ignore
                if (context.is404) {
                    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
        var 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", {
                path: url,
                content: tpl,
            })
        }

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