const logger = require('../utils/log.cjs')
const routes = require('./routes.cjs')
const httpProxy = require('http-proxy')
const proxy = httpProxy.createProxyServer({})
const fs = require('fs')
const url = require('url')
const axios = require('axios')
const dist = 'dist'
let mime
import('mime').then((res) => {
    mime = res.default
})
let proxys = require('../../../src/proxy.cjs')
const { Exception } = require("sass");
const httpOk = 200
const httpBadRequest = 400
const matchProxy = (request, response) => {
    const match = request.url.split('/')[1]
    const proxyInfo = proxys['/' + match]
    if (proxyInfo) {
        const host = request.headers.host;
        delete request.headers.host
        if (typeof proxyInfo.rewrite === 'function') {
            request.url = proxyInfo.rewrite(request.url)
        }
        proxy.web(request, response, {
            target: proxyInfo.target || ("http://" + host),
            changeOrigin: proxyInfo.changeOrigin
        })
        logger.info(`${request.method} ${httpOk} ${request.url}`)
        return true
    } else {
        return null
    }
}
const matchRouter = async (request, response) => {
    let [url] = request.url.split('?')
    let route = routes
    let url_sp = url.split('/')
    for (let p of url_sp) {
        if (!p) {
            continue
        }
        if (route[p]) {
            route = route[p]
        } else {
            return false
        }
    }
    if (typeof route === 'function') {
        await route(request, response)
        // response.writeHead(httpOk, { 'Content-Type': 'application/json' })
        // response.end(JSON.stringify(res))
        logger.info(`${request.method} ${httpOk} ${request.url}`)
        return true
    } else {
        return false
    }
}
function getMimeType(filePath) {
    const ext = filePath.split('.').pop()?.toLowerCase()
    const defaultMimes = {
        png: 'image/png',
        jpg: 'image/jpeg',
        jpeg: 'image/jpeg',
        gif: 'image/gif',
        webp: 'image/webp',
        svg: 'image/svg+xml',
        ico: 'image/x-icon',
        js: 'text/javascript',
        css: 'text/css',
        html: 'text/html',
        json: 'application/json',
        woff: 'font/woff',
        woff2: 'font/woff2',
        ttf: 'font/ttf',
        otf: 'font/otf'
    }
    if (ext && defaultMimes[ext]) {
        return defaultMimes[ext]
    }
    if (mime && typeof mime.getType === 'function') {
        return mime.getType(filePath) || 'application/octet-stream'
    }
    return 'application/octet-stream'
}

const matchFile = async (request, response) => {
    return new Promise((resolve) => {
        const cleanPath = decodeURIComponent(request.url.split('?')[0])
        fs.readFile(dist + cleanPath, (err, file) => {
            if (!err) {
                const mimetype = getMimeType(cleanPath)
                const responseHdeaders = { 'Content-Type': mimetype }
                if (cleanPath.endsWith("-sw.js")) {
                    responseHdeaders["Service-Worker-Allowed"] = '/'
                }
                response.writeHead(httpOk, responseHdeaders)
                response.end(file)
                // logger.info(`${request.method} ${httpOk} ${request.url}`)
                resolve(true)
            } else {
                resolve(false)
            }
        })
    })
}

const endIndex = async (request, response) => {
    fs.readFile(dist + '/index.html', 'utf-8', async (err, html) => {
        if (!err) {
            let finalHtml = html
            try {
                const parsedUrl = url.parse(request.url, true)
                if (parsedUrl.pathname === '/article-detail' && parsedUrl.query.id) {
                    const id = parsedUrl.query.id
                    const res = await axios.get(`http://wechat.wenyitu.com/api/articles/${id}`)
                    const article = res.data
                    if (article) {
                        if (article.title) {
                            finalHtml = finalHtml.replace(/<title>.*?<\/title>/, `<title>${article.title} - 装样大师</title>`)
                        }
                        if (article.seo_keywords) {
                            finalHtml = finalHtml.replace(/<meta name="keywords" content="[^"]*"/, `<meta name="keywords" content="${article.seo_keywords}"`)
                        }
                        if (article.seo_description) {
                            finalHtml = finalHtml.replace(/<meta name="description" content="[^"]*"/, `<meta name="description" content="${article.seo_description}"`)
                        }
                    }
                } else if (parsedUrl.pathname === '/article' && parsedUrl.query.category_id) {
                    const categoryId = parsedUrl.query.category_id
                    const res = await axios.get(`http://wechat.wenyitu.com/api/articles?category_id=${categoryId}&page=1&per_page=10`)
                    const data = res.data
                    if (data && data.items && data.items.length > 0 && data.items[0].category) {
                        const category = data.items[0].category
                        if (category.seo_keywords) {
                            finalHtml = finalHtml.replace(/<meta name="keywords" content="[^"]*"/, `<meta name="keywords" content="${category.seo_keywords}"`)
                        }
                        if (category.seo_description) {
                            finalHtml = finalHtml.replace(/<meta name="description" content="[^"]*"/, `<meta name="description" content="${category.seo_description}"`)
                        }
                    }
                }
            } catch (e) {
                logger.error('获取文章详情用于SEO渲染失败: ' + String(e))
            }
            
            response.writeHead(httpOk, { 'Content-type': 'text/html;charset=utf-8' })
            response.end(finalHtml)
            logger.info(`${request.method} ${httpOk} ${request.url}`)
        }
    })
}

const matchType = async (request, response) => {
    const isRouter = await matchRouter(request, response)
    if (isRouter) {
        return
    }
    let isFile = await matchFile(request, response)
    if (isFile) {
        return
    }
    let isProxy = matchProxy(request, response)
    if (isProxy) {
        return
    }
    await endIndex(request, response)
}

const httpService = async (request, response) => {
    try {
        await matchType(request, response)
    } catch (e) {
        response.writeHead(httpBadRequest, { 'Content-Type': 'application/json' })
        response.end(
            JSON.stringify({
                code: -1,
                message: String(e)
            })
        )
        logger.info(`${request.method} ${httpBadRequest} ${request.url}`)
    }
}
module.exports = {
    httpService,
    matchType,
    matchRouter,
    matchFile,
    endIndex,
    matchProxy,
}
