// http.js 的 main 函数是http服务的所有脚本函数执行的预处理入口
function main() {
    // 当前时间
    let time = new Date()
    let timeStr = time.toUTCString()
    response.headers.set("Date", timeStr)
    payload.set.header("Timestamp", time.getTime())

    // 安全性检查
    'use api/lib/sourceAnti.js'

    'use api/lib/setResponseHeaders.js'

    let req = payload.get()

    if (!req?.headers['Cache-Control'] || !req?.headers['Cache-Control']['skip-cache']) {
        // 从Header、Query、Cookie、Body中获取token
        let userToken = req?.headers?.Authorization || req?.query?.token || req?.headers["X-Token"] || req?.cookie?.token
        var signature = `${req.method}:${req.host}:${req.url}::${req.url}:${userToken}:${req.body ? req.body.toString() : '>'}`
        signature = crypto.hash.md5(signature).toHEX.encoding().toString()
        // 缓存5秒 - 缓存命中则直接返回
        let cacheData = cache.get('results', signature)
        if (cacheData && cacheData != '') {
            response.contentType.json()
            response.headers.set("Cache-Status", "hit")
            response.headers.set("Cache-Key", signature)
            // 如果请求头中包含 Accept-Encoding 并且 Accept-Encoding 的值包含 br，则设置 Content-Encoding 为 br。
            if (req.headers['Accept-Encoding'] && req.headers['Accept-Encoding'][0].includes('br')) {
                response.headers.set("Content-Encoding", 'br')
            }

            var currentTime = new Date();
            let timeDiff = currentTime - time
            response.headers.set("Server-Timing", `RequestCost;dur=${timeDiff}`)
            // currentTime.setSeconds(currentTime.getSeconds() + 5);
            // var timeAfter = currentTime.toUTCString();
            // response.headers.set("Expires", timeAfter)
            response.headers.set("Cache-Control", `no-transform,no-siteapp,max-age=5`)

            response.write(cacheData)
            return
        }
    }

    // 声明路径
    let filePath = req.path.substring(1)

    // 如果Header加上Cache-Control:*则移除缓存，本次访问将不会命中缓存，有刷新效果。
    if (req?.headers['Cache-Control'] && req?.headers['Cache-Control']['clear']) {
        runtime.cache.remove(filePath)
        response.headers.set("Clear-Site-Data", '"*"')
    }

    switch (req.method) {
        case 'OPTIONS':
            // 这样对于所有的 OPTIONS 请求都会返回 200 (OK) 状态码
            response.status.ok()
            return
        // 当接收的请求为 GET 时
        case 'GET':
            // 特殊访问路径
            // JWK
            if (filePath == '.well-known/jwks.json') {
                response.contentType.json()
                response.write(`{"keys":[{"kty":"SM2","e":"AQAB","n":"${SYSTEM_CONFIG.find(item => item.name === 'system_jwt_public').value.replace(/--.*\n/, "").replace(/\n.*--/, "")}","alg":"SS256","use":"sig","kid":"${ex.suid().base58()}"}]}`)
                return
            }

            // 【安全须知】
            // 原则上所有命名以.和_开头的目录或文件都不允许直接被访问
            // 因为它们很大概率是系统文件或非开放文件
            if (!filePath.startsWith('.well-known') && (filePath.startsWith('.') || filePath.startsWith('_'))) {
                response.status.code(404)
                return `404 page not found`
            }

            // 可访问的脚本路径
            let allowScriptPath = [
                'static/index.js',
                'static/js/md5.js',
            ]

            // 【安全须知】
            // 原则上所有的js文件都不允许直接被访问，以免源代码泄露，所以返回404。
            // 如果需要将js对外暴露，请在allowScriptPath中添加。
            // 但app目录内的所有js文件除外，因为该目录用于放置前端页面
            if (filePath.endsWith('.js') && !filePath.startsWith('app') && !allowScriptPath.includes(filePath)) {
                response.status.code(404)
                return `404 page not found`
            }

            response.headers.set("Content-Type", "text/html; charset=utf-8;");

            // 判断是否为目录以及否存在index.html或index.html文件，如果存在则返回index.html或index.htm文件
            if (filePath[filePath.length - 1] == "/" || filePath == "" || fs.isDir(filePath)) {
                if (filePath == "") {
                    filePath = rootPath
                }
                let tmp = fs.join(filePath, 'index.htm')
                if (fs.exists(tmp)) {
                    filePath = tmp
                    response.file(filePath)
                    return
                }
                tmp += "l"
                if (fs.exists(tmp)) {
                    filePath = tmp
                    response.file(filePath)
                    return
                }
            }

            // 获取文件类型
            'use api/lib/getFileMimeType.js'
            response.headers.set('Content-Type', getFileMimeType(filePath))

            // 如果不是目录，则尝试返回文件
            if (fs.exists(filePath) && !fs.isDir(filePath)) {
                const fileSqlPath = req.path

                if (fileSqlPath.includes('/uploads/')) {
                    // 查询数据库中是否有该文件的信息
                    const file_info = SQL.query('system_sql', 'SELECT * FROM sys_files WHERE file_id = ?', req.path.split("/").pop())
                    if (file_info.length > 0) {
                        // 判断文件是否已删除
                        if (file_info[0].delete_time) {
                            return errMsg(404, '文件已删除')
                        }

                        filePath = rootPath + file_info[0].file_path

                        response.headers.add('X-File-Id', file_info[0].file_id)
                        response.headers.add('X-File-Name', file_info[0].file_name)
                        response.headers.add('X-File-Size', file_info[0].file_size)
                        response.headers.add('X-File-Owner', file_info[0].user_id)
                        response.headers.add('X-File-Create-Date', file_info[0].create_time)
                        response.headers.set('Content-Type', file_info[0].file_type)

                        // 设置 Content-Disposition
                        response.headers.set('Content-Disposition', 'filename=' + file_info[0].file_name)
                    }
                }

                if (req.query.download) {
                    // 设置 Content-Disposition
                    response.headers.add('Content-Disposition', 'attachment')
                }

                var currentTime = new Date();
                let timeDiff = currentTime - time
                response.headers.set("Server-Timing", `RequestCost;dur=${timeDiff}`)
                // 如果文件存在，则返回文件
                response.file(filePath)
                return
            }
    }

    // 默认情况下返回的内容都是JSON格式的，所以在这里预设 Content-Type 为 application/json
    response.headers.set("Content-Type", "application/json; charset=utf-8;");

    // 声明缓存
    response.headers.set(
        'Cache-Control',
        'no-transform,no-cache,immutable'
    )

    // payload.set.header('Signet', '/__/vlan/')

    //
    // 判断filePath存在，则将请求移交给 filePath 下的 function.js 进行处理。
    if (fs.exists(filePath)) {
        runtime.goto(filePath, ...args)
        return
    }
    // 如果不存在，则尝试调用filepath的上一级目录下的function.js
    // const parentDir = filePath.substr(0, filePath.lastIndexOf('/'))
    runtime.goto(findValidPath(filePath), ...args) // goto会将 return 的内容写到 response.body 里面。但call不会。
    return
}

// 递归路径
cache.new('route-path')
function findValidPath(filePath) {
    // 尝试从缓存获取
    const cachedPath = cache.get('route-path', filePath);
    if (cachedPath) return cachedPath;

    // 自上而下查找最深的有效路径
    const pathParts = filePath.split('/').filter(Boolean);
    let currentPath = '';

    for (const part of pathParts) {
        const testPath = currentPath ? fs.join(currentPath, part) : part;
        if (!fs.exists(testPath)) break;
        currentPath = testPath;
    }

    const result = currentPath || './';

    // 缓存结果
    cache.set('route-path', filePath, result, 60 * 1000); // 60秒缓存

    return result;
}
