/**
 * 嘉義縣電腦教室學生檔案傳輸系統
 * 功能：班級管理、座號驗證隱私機制、教師後台權限管控、變更管理密碼
 * 特色：全面支援中文檔名上傳與下載、自動偵測並顯示主機真實 IP
 * 依賴：express, multer, body-parser, fs-extra, express-session
 */

const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs-extra');
const bodyParser = require('body-parser');
const session = require('express-session');
const os = require('os'); // 引入 os 模組以獲取網路介面資訊

const app = express();
const PORT = 3000;

// 設定基礎路徑
const STORAGE_ROOT = path.join(__dirname, 'classroom_data');
const CONFIG_FILE = path.join(__dirname, 'config.json');

// 初始化資料夾與設定
if (!fs.existsSync(STORAGE_ROOT)) fs.mkdirSync(STORAGE_ROOT);

let config = { 
    classes: {}, 
    adminPassword: 'cyc2026' // 預設管理密碼
}; 

if (fs.existsSync(CONFIG_FILE)) {
    try {
        const savedConfig = fs.readJsonSync(CONFIG_FILE);
        config = { ...config, ...savedConfig };
    } catch (e) {
        console.error("讀取設定檔失敗:", e);
    }
} else {
    fs.writeJsonSync(CONFIG_FILE, config);
}

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// 設定 Session
app.use(session({
    secret: 'chiayi-county-secret',
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 3600000 }
}));

// 設定上傳組態 - 強化對中文檔名的支援
const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        const className = req.params.className;
        const dest = path.join(STORAGE_ROOT, className);
        fs.ensureDirSync(dest); 
        cb(null, dest);
    },
    filename: (req, file, cb) => {
        const studentId = req.body.studentId || '00';
        const studentName = req.body.studentName || '匿名';
        
        // 處理中文檔名編碼
        const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8');
        const safeName = originalName.replace(/[\\/:*?"<>|]/g, '_');
        
        cb(null, `${studentId}_${studentName}_${Date.now()}_${safeName}`);
    }
});

const upload = multer({ 
    storage: storage,
    limits: { fileSize: 500 * 1024 * 1024 } 
});

// 中間件：檢查管理員是否登入
const isAdmin = (req, res, next) => {
    if (req.session.adminLoggedIn) {
        next();
    } else {
        res.redirect('/admin/login');
    }
};

// --- 前端頁面模板 ---
const getLayout = (content, showAdminLogout = false) => `
<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>嘉義縣電腦教室學生檔案傳輸系統</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        body { background-color: #f0f4f8; font-family: "Microsoft JhengHei", "PingFang TC", sans-serif; }
        .card { background: white; border-radius: 12px; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); padding: 2rem; }
        .gradient-bg { background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%); }
    </style>
</head>
<body class="p-4 md:p-8">
    <div class="max-w-5xl mx-auto">
        <header class="mb-8 flex flex-col md:flex-row justify-between items-center border-b-2 border-blue-200 pb-6">
            <div onclick="location.href='/'" class="cursor-pointer mb-4 md:mb-0">
                <h1 class="text-3xl font-extrabold text-blue-800 tracking-tight">嘉義縣電腦教室</h1>
                <p class="text-blue-600 font-medium text-lg">學生檔案傳輸系統</p>
            </div>
            <div class="flex gap-2">
                ${showAdminLogout ? `
                    <button onclick="location.href='/admin/change-pw'" class="bg-yellow-500 text-white px-4 py-2 rounded shadow hover:bg-yellow-600 transition">變更管理密碼</button>
                    <button onclick="location.href='/admin/logout'" class="bg-red-500 text-white px-4 py-2 rounded shadow hover:bg-red-600 transition">登出</button>
                ` : `
                    <button onclick="location.href='/admin'" class="bg-blue-600 text-white px-5 py-2 rounded-full shadow hover:bg-blue-700 transition font-bold">教師管理入口</button>
                `}
            </div>
        </header>
        ${content}
        <footer class="mt-12 text-center text-gray-400 text-sm italic">
            &copy; 2026 嘉義縣電腦教室教學環境系統
        </footer>
    </div>
</body>
</html>
`;

// --- 路由 ---

app.get('/', (req, res) => {
    const classList = Object.keys(config.classes);
    let html = '<h2 class="text-2xl font-bold mb-6 text-gray-800 flex items-center">📁 請選擇所屬班級：</h2>';
    html += '<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">';
    if (classList.length === 0) {
        html += '<div class="col-span-full card text-center py-16 text-gray-500 text-xl italic">目前尚無班級資料，請聯繫教師建立。</div>';
    }
    classList.forEach(cls => {
        html += `
            <div class="card hover:shadow-2xl transition-all cursor-pointer transform hover:-translate-y-1 text-center border-b-4 border-blue-500" onclick="location.href='/class/${cls}'">
                <div class="text-5xl mb-3">🏫</div>
                <div class="text-2xl font-black text-gray-800">${cls} 班</div>
            </div>
        `;
    });
    html += '</div>';
    res.send(getLayout(html));
});

app.get('/class/:className', async (req, res) => {
    const { className } = req.params;
    const viewId = req.query.viewId || '';
    if (!config.classes[className]) return res.redirect('/');

    const classDir = path.join(STORAGE_ROOT, className);
    await fs.ensureDir(classDir);
    const allFiles = await fs.readdir(classDir);
    const myFiles = viewId ? allFiles.filter(f => f.startsWith(`${viewId}_`)) : [];

    let html = `
        <div class="mb-6 flex items-center text-blue-600 font-bold">
            <a href="/" class="hover:text-blue-800 transition">← 返回班級列表</a>
            <span class="mx-2">/</span>
            <span>當前位置：${className} 班</span>
        </div>
        
        <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
            <div class="card border-t-4 border-blue-600">
                <h2 class="text-2xl font-bold mb-6 text-blue-800">📤 作業上傳</h2>
                <form action="/upload/${className}" method="POST" enctype="multipart/form-data" class="space-y-5">
                    <div>
                        <label class="block mb-2 text-sm font-bold text-gray-700">班級通行碼：</label>
                        <input type="password" name="password" required class="w-full border-2 border-gray-200 p-3 rounded-lg focus:border-blue-500 outline-none transition">
                    </div>
                    <div class="grid grid-cols-2 gap-4">
                        <div>
                            <label class="block mb-2 text-sm font-bold text-gray-700">學生座號：</label>
                            <input type="number" name="studentId" required min="1" max="60" class="w-full border-2 border-gray-200 p-3 rounded-lg focus:border-blue-500 outline-none transition">
                        </div>
                        <div>
                            <label class="block mb-2 text-sm font-bold text-gray-700">姓名 (選填)：</label>
                            <input type="text" name="studentName" class="w-full border-2 border-gray-200 p-3 rounded-lg focus:border-blue-500 outline-none transition">
                        </div>
                    </div>
                    <div>
                        <label class="block mb-2 text-sm font-bold text-gray-700">選擇檔案 (支援中文檔名)：</label>
                        <input type="file" name="file" required class="block w-full text-sm text-gray-500 file:mr-4 file:py-3 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-bold file:bg-blue-600 file:text-white cursor-pointer">
                    </div>
                    <button type="submit" class="w-full gradient-bg text-white font-black py-4 rounded-lg shadow-lg">確認送出作業</button>
                </form>
            </div>

            <div class="card border-t-4 border-green-600">
                <h2 class="text-2xl font-bold mb-6 text-green-800">📂 我的繳交紀錄</h2>
                <div class="flex gap-2 mb-6">
                    <input type="number" id="viewIdInput" value="${viewId}" placeholder="輸入座號" class="flex-1 border-2 border-gray-200 p-3 rounded-lg focus:border-green-500 outline-none">
                    <button onclick="viewMyFiles()" class="bg-green-600 text-white px-6 py-3 rounded-lg font-bold">查詢</button>
                </div>
                <div class="bg-gray-50 rounded-xl p-4 min-h-[200px]">
                    ${viewId ? `
                        <div class="overflow-x-auto">
                            <table class="w-full text-left">
                                <tbody class="text-gray-700">
                                    ${myFiles.map(f => {
                                        const cleanName = f.split('_').slice(3).join('_');
                                        return `
                                        <tr class="border-b last:border-0 hover:bg-white transition">
                                            <td class="py-3 truncate max-w-[180px] font-medium text-sm">${cleanName}</td>
                                            <td class="py-3 text-right">
                                                <a href="/download/${className}/${encodeURIComponent(f)}" class="text-blue-700 text-sm font-bold underline">下載</a>
                                            </td>
                                        </tr>`}).join('')}
                                </tbody>
                            </table>
                            ${myFiles.length === 0 ? '<p class="text-center py-10 text-gray-400">查無資料</p>' : ''}
                        </div>
                    ` : '<div class="flex items-center justify-center h-full text-gray-400 italic">請輸入座號查詢</div>'}
                </div>
            </div>
        </div>
        <script>
            function viewMyFiles() {
                const id = document.getElementById('viewIdInput').value;
                if(!id) return alert('請輸入座號');
                location.href = '?viewId=' + id;
            }
        </script>
    `;
    res.send(getLayout(html));
});

// --- 上傳邏輯 ---
app.post('/upload/:className', (req, res) => {
    const { className } = req.params;
    if (!config.classes[className]) return res.status(404).send("班級不存在");

    upload.single('file')(req, res, (err) => {
        if (err) {
            console.error("上傳過程錯誤:", err);
            return res.send(`<script>alert('上傳出錯: ${err.message}'); window.history.back();</script>`);
        }

        const { password, studentId } = req.body;
        const correctPassword = config.classes[className].password;

        if (password !== correctPassword) {
            if (req.file) fs.remove(req.file.path).catch(e => console.error("清理失敗:", e));
            return res.send("<script>alert('班級通行碼錯誤！'); window.history.back();</script>");
        }

        if (!req.file) return res.send("<script>alert('未選擇檔案！'); window.history.back();</script>");

        res.send(`<script>alert('作業已成功傳送！'); window.location.href='/class/${className}?viewId=${studentId}';</script>`);
    });
});

// --- 下載邏輯 ---
app.get('/download/:className/:fileName', (req, res) => {
    const { className, fileName } = req.params;
    const decodedFileName = decodeURIComponent(fileName);
    const filePath = path.join(STORAGE_ROOT, className, decodedFileName);
    
    if (fs.existsSync(filePath)) {
        res.download(filePath, decodedFileName);
    } else {
        res.status(404).send("檔案不存在");
    }
});

// --- 教師管理路由 (省略部分重複代碼以節省篇幅，邏輯同前) ---
app.get('/admin/login', (req, res) => {
    let html = `<div class="max-w-md mx-auto card mt-10 border-t-8 border-blue-900"><h2 class="text-2xl font-black mb-6 text-center text-blue-900">教師管理登入</h2><form action="/admin/login" method="POST" class="space-y-6"><input type="password" name="adminPassword" required autofocus class="w-full border-2 p-4 rounded-xl" placeholder="管理密碼"><button type="submit" class="w-full bg-blue-900 text-white font-bold py-4 rounded-xl">登入系統</button></form></div>`;
    res.send(getLayout(html));
});

app.post('/admin/login', (req, res) => {
    if (req.body.adminPassword === config.adminPassword) {
        req.session.adminLoggedIn = true;
        res.redirect('/admin');
    } else {
        res.send("<script>alert('密碼錯誤！'); window.history.back();</script>");
    }
});

app.get('/admin/logout', (req, res) => {
    req.session.destroy();
    res.redirect('/');
});

app.get('/admin', isAdmin, async (req, res) => {
    const selectedClass = req.query.class;
    let fileTable = '';
    if (selectedClass) {
        const classDir = path.join(STORAGE_ROOT, selectedClass);
        await fs.ensureDir(classDir);
        const files = await fs.readdir(classDir);
        fileTable = `<div class="mt-10 card border-2 border-red-100"><h3 class="text-xl font-black text-red-700 mb-4">【${selectedClass} 班】檔案清單</h3><div class="overflow-x-auto"><table class="w-full text-left"><thead class="bg-gray-50 text-sm"><tr><th class="p-3 border">座號</th><th class="p-3 border">姓名</th><th class="p-3 border">檔名</th><th class="p-3 border text-center">操作</th></tr></thead><tbody>${files.map(f => {const p = f.split('_'); return `<tr><td class="p-3 border">${p[0]}</td><td class="p-3 border">${p[1]}</td><td class="p-3 border text-xs truncate max-w-xs">${p.slice(3).join('_')}</td><td class="p-3 border text-center"><a href="/download/${selectedClass}/${encodeURIComponent(f)}" class="text-blue-600 mr-2 font-bold">下載</a><button onclick="deleteFile('${selectedClass}', '${f}')" class="text-red-500 font-bold">刪除</button></td></tr>`}).join('')}</tbody></table></div></div>`;
    }
    let html = `<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"><div class="card border-l-8 border-green-600"><h2 class="text-lg font-bold mb-4">建立班級</h2><form action="/admin/add-class" method="POST" class="space-y-4"><input type="text" name="className" placeholder="班級" required class="w-full border p-2 rounded"><input type="text" name="password" placeholder="學生密碼" required class="w-full border p-2 rounded"><button type="submit" class="w-full bg-green-700 text-white py-2 rounded">建立</button></form></div><div class="card md:col-span-2 border-l-8 border-blue-800"><h2 class="text-lg font-bold mb-4">班級列表</h2><table class="w-full text-sm"><thead><tr class="text-gray-400 border-b"><th>班級</th><th>密碼</th><th>管理</th></tr></thead><tbody>${Object.keys(config.classes).map(cls => `<tr class="border-b"><td class="py-2 font-bold">${cls} 班</td><td class="py-2">${config.classes[cls].password}</td><td class="py-2"><a href="/admin?class=${cls}" class="text-blue-600 mr-3 font-bold">查看檔案</a><button onclick="deleteClass('${cls}')" class="text-red-500 font-bold">刪除</button></td></tr>`).join('')}</tbody></table></div></div>${fileTable}<script>async function deleteClass(name){if(confirm('確定刪除班級與檔案？')){await fetch('/admin/delete-class',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({className:name})});location.href='/admin';}}async function deleteFile(cls,file){if(confirm('確定刪除檔案？')){await fetch('/admin/delete-file',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({className:cls,fileName:file})});location.reload();}}</script>`;
    res.send(getLayout(html, true));
});

app.get('/admin/change-pw', isAdmin, (req, res) => {
    let html = `<div class="max-w-md mx-auto card border-t-8 border-yellow-500"><h2 class="text-2xl font-black mb-6">🔐 變更管理密碼</h2><form action="/admin/change-pw" method="POST" class="space-y-6"><input type="password" name="newPassword" required class="w-full border-2 p-4 rounded-xl" placeholder="輸入新密碼"><button type="submit" class="w-full bg-yellow-500 text-white font-bold py-4 rounded-xl">確認變更</button></form></div>`;
    res.send(getLayout(html, true));
});

app.post('/admin/change-pw', isAdmin, (req, res) => {
    config.adminPassword = req.body.newPassword;
    fs.writeJsonSync(CONFIG_FILE, config);
    res.send("<script>alert('密碼已更換，請重新登入'); window.location.href='/admin/logout';</script>");
});

app.post('/admin/add-class', isAdmin, (req, res) => {
    const { className, password } = req.body;
    config.classes[className] = { password };
    fs.writeJsonSync(CONFIG_FILE, config);
    fs.ensureDirSync(path.join(STORAGE_ROOT, className));
    res.redirect('/admin');
});

app.post('/admin/delete-class', isAdmin, async (req, res) => {
    const { className } = req.body;
    delete config.classes[className];
    fs.writeJsonSync(CONFIG_FILE, config);
    await fs.remove(path.join(STORAGE_ROOT, className));
    res.json({ success: true });
});

app.post('/admin/delete-file', isAdmin, async (req, res) => {
    const { className, fileName } = req.body;
    await fs.remove(path.join(STORAGE_ROOT, className, fileName));
    res.json({ success: true });
});

// --- 啟動伺服器並顯示區域網路 IP ---
app.listen(PORT, '0.0.0.0', () => {
    const interfaces = os.networkInterfaces();
    let localIp = '127.0.0.1';
    
    // 遍歷網路介面找出 IPv4 的網卡地址
    for (const devName in interfaces) {
        const iface = interfaces[devName];
        for (let i = 0; i < iface.length; i++) {
            const alias = iface[i];
            if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
                localIp = alias.address;
            }
        }
    }

    console.log(`======================================================`);
    console.log(`🚀 系統啟動成功！`);
    console.log(`系統名稱: 嘉義縣電腦教室學生檔案傳輸系統`);
    console.log(`學生連線網址: http://${localIp}:${PORT}`);
    console.log(`======================================================`);
});

process.on('uncaughtException', (err) => {
    console.error('未擷取的異常:', err);
});