const express = require('express');
const https = require('https');
const cors = require('cors');
const path = require('path');
const fs = require('fs');
const morgan = require('morgan');
const rateLimit = require('express-rate-limit');
const logger = require('./utils/logger');
const auditLogger = require('./middleware/auditLogger');
const { checkDiskSpace } = require('./utils/diskMonitor');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 3000;

// 信任反向代理 (Nginx)
// 必须设置此项，否则在 Nginx 后端运行时，req.ip 永远是 127.0.0.1，导致限流策略对所有用户生效（误伤）
app.set('trust proxy', 1);

// 中间件
app.use(cors({
    origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
    credentials: true
}));
app.use(express.json());

// 定义脱敏的 URL token
morgan.token('safe-url', (req) => {
    let url = req.originalUrl || req.url;
    try {
        // 隐藏 token, password, code 等敏感参数
        url = url.replace(/([?&])(token|password|code)=([^&]+)/gi, '$1$2=***');
    } catch (e) {
        // 忽略错误
    }
    return url;
});

// HTTP 请求日志 (使用自定义格式，替换 :url 为 :safe-url)
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :safe-url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"', { stream: logger.stream }));

// 全局审计日志
app.use(auditLogger);

// 限流策略配置
// 1. 全局限流：每个IP每分钟最多100次请求
const globalLimiter = rateLimit({
    windowMs: 1 * 60 * 1000, // 1分钟
    max: 100, // 限制每个IP 100次请求
    standardHeaders: true, // 返回 `RateLimit-*` 头信息
    legacyHeaders: false, // 禁用 `X-RateLimit-*` 头信息
    message: { message: '请求过于频繁，请稍后再试' }
});

// 2. 认证接口限流：每个IP每分钟最多10次请求 (防暴力破解)
const authLimiter = rateLimit({
    windowMs: 1 * 60 * 1000, // 1分钟
    max: 10, // 限制每个IP 10次请求
    standardHeaders: true,
    legacyHeaders: false,
    message: { message: '登录/注册尝试过于频繁，请1分钟后再试' }
});

// 应用全局限流
app.use('/api/', globalLimiter);

// 安全策略：禁止移动端访问
app.use((req, res, next) => {
    const userAgent = req.headers['user-agent'] || '';
    // 匹配常见的移动设备标识
    const isMobile = /mobile|android|iphone|ipad|phone/i.test(userAgent);
    
    if (isMobile) {
        res.status(403).send(`
            <html>
                <head><title>访问被拒绝</title></head>
                <body style="display:flex;justify-content:center;align-items:center;height:100vh;font-family:sans-serif;background:#f0f2f5;">
                    <div style="text-align:center;padding:40px;background:white;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,0.15);">
                        <h1 style="color:#ff4d4f;">🚫 访问被拒绝</h1>
                        <p style="font-size:18px;color:#333;">根据本单位安全规定，本系统<strong>禁止使用移动设备</strong>访问。</p>
                        <p style="color:#666;">请使用办公电脑访问。</p>
                    </div>
                </body>
            </html>
        `);
        return;
    }
    next();
});

// 确保上传目录存在
const uploadDir = process.env.UPLOAD_DIR || 'uploads';
let absoluteUploadDir;
if (path.isAbsolute(uploadDir)) {
    absoluteUploadDir = uploadDir;
} else {
    absoluteUploadDir = path.join(__dirname, uploadDir);
}

if (!fs.existsSync(absoluteUploadDir)) {
    fs.mkdirSync(absoluteUploadDir, { recursive: true });
}

const DISK_MONITOR_ENABLED = String(process.env.DISK_MONITOR_ENABLED || 'true').toLowerCase() !== 'false';
const DISK_CHECK_INTERVAL_MINUTES = Number(process.env.DISK_CHECK_INTERVAL_MINUTES || 60);
const DISK_CHECK_INTERVAL_MS = Number.isFinite(DISK_CHECK_INTERVAL_MINUTES) && DISK_CHECK_INTERVAL_MINUTES > 0
    ? DISK_CHECK_INTERVAL_MINUTES * 60 * 1000
    : 60 * 60 * 1000;

// 启动磁盘监控（默认每 60 分钟检查一次）
if (DISK_MONITOR_ENABLED) {
    setInterval(() => {
        checkDiskSpace();
    }, DISK_CHECK_INTERVAL_MS);

    // 启动时立即检查一次
    checkDiskSpace();
}

// 导入路由
const authRoutes = require('./routes/auth');
const achievementRoutes = require('./routes/achievements');
const userRoutes = require('./routes/users');
const statisticsRoutes = require('./routes/statistics');
const dictionaryRoutes = require('./routes/dictionaries');
const logRoutes = require('./routes/logs');
const notificationRoutes = require('./routes/notifications');
const aiAnalysisRoutes = require('./routes/aiAnalysis');

// 对认证路由应用更严格的限流
app.use('/api/auth', authLimiter, authRoutes);
app.use('/api/achievements', achievementRoutes);
app.use('/api/users', userRoutes);
app.use('/api/statistics', statisticsRoutes);
app.use('/api/dictionaries', dictionaryRoutes);
app.use('/api/logs', logRoutes);
app.use('/api/notifications', notificationRoutes);
app.use('/api/ai-analysis', aiAnalysisRoutes);

// 静态文件服务 (用于开发环境查看附件，生产环境建议用 Nginx)
app.use('/uploads', express.static(absoluteUploadDir, {
    setHeaders: (res, path) => {
        // 强制下载，防止浏览器直接预览 HTML/SVG 等可能包含脚本的文件
        res.setHeader('Content-Disposition', 'attachment');
    }
}));

// 托管前端静态文件 (生产环境)
const clientBuildPath = path.join(__dirname, '../client/build');
if (fs.existsSync(clientBuildPath)) {
    app.use(express.static(clientBuildPath));
    // 使用正则表达式排除以 /api/ 开头的路径
    app.get(/^(?!\/api\/).*$/, (req, res) => {
        res.sendFile(path.join(clientBuildPath, 'index.html'));
    });
}

// 尝试读取 SSL 证书 (用于 HTTPS)
const keyPath = path.join(__dirname, 'server.key');
const certPath = path.join(__dirname, 'server.cert');

if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
    // 如果存在证书，启动 HTTPS 服务器
    const options = {
        key: fs.readFileSync(keyPath),
        cert: fs.readFileSync(certPath)
    };
    https.createServer(options, app).listen(PORT, () => {
        const msg = `HTTPS 安全服务器运行在 https://localhost:${PORT}`;
        console.log(msg);
        logger.info(msg);
        console.log(`局域网访问请使用: https://<你的IP>:${PORT}`);
    });
} else {
    // 否则启动标准 HTTP 服务器
    app.listen(PORT, () => {
        const msg = `HTTP 服务器运行在 http://localhost:${PORT}`;
        console.log(msg);
        logger.info(msg);
        console.log(`提示: 未检测到 server.key 和 server.cert，已降级为 HTTP 模式。`);
    });
}

