const path = require('path')
const db = require("../plugin/DataBase/db")
const Logger = require('./Logger')
const ipSearcher = require('../plugin/ip2region')

class RequestLog {
    constructor() {
        this.logger = new Logger()
        this.searcher = ipSearcher.newWithFileOnly(path.join(__dirname, '../plugin/ip2region/ip2region.xdb'))
    }

    async insertLog(req, resData, namespace, method, path) {
        try {
            const time = Date.now();
            const ip = this.getClientIp(req);

            let ipData
            try {
                let ipInfo = await this.searcher.search(ip)
                ipData = ipInfo?.region ?? null
            } catch {
                ipData = null
            }

            const userAgent = req.headers['user-agent'] ?? null;
            const deviceType = req.headers['device-type'] ?? '浏览器'

            let reqData = method.toLowerCase() === 'get' ? req.query : req.body

            const safe = (v) => (v === undefined ? null : v)

            const sql = `
            INSERT INTO requestLog 
            (create_user, create_time, method, reqData, resData, code, ip, ua, deviceType, apiName, location, url) 
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `

            const params = [
                safe(reqData?.uuid) ?? '',                // create_user
                time,                                     // create_time
                method,                                   // method
                JSON.stringify(reqData ?? {}),            // reqData
                JSON.stringify(resData ?? {}),            // resData
                safe(resData?.code),                      // code
                safe(ip),                                 // ip
                safe(userAgent),                          // ua
                safe(deviceType),                         // deviceType
                namespace ?? '未知',                       // apiName
                safe(ipData) ?? '未知',                    // location
                path                                      // url
            ];

            let r = await db.query(sql, params)
            if (!r || r.affectedRows !== 1) {
                this.logger.error(`插入日志信息失败！数据库错误`)
            }
        } catch (error) {
            this.logger.error(`插入日志信息失败！${error}`)
        }
    }

    getClientIp(req) {
        let ip = null

        if (req.headers['x-forwarded-for']) {
            ip = req.headers['x-forwarded-for'].split(',')[0].trim();
        } else if (req.headers['x-real-ip']) {
            ip = req.headers['x-real-ip'];
        } else {
            ip = req.connection.remoteAddress || ''
        }

        // 如果是 IPv6 映射的 IPv4 (::ffff:x.x.x.x)，提取后面的 IPv4
        if (ip.startsWith("::ffff:")) {
            ip = ip.replace("::ffff:", "")
        }

        // 如果是 [::1] 或其他 IPv6
        const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/
        if (!ipv4Regex.test(ip)) {
            return '0.0.0.0'; // 非 IPv4
        }

        return ip ?? '0.0.0.0';
    }

}

module.exports = RequestLog