const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const Database = require('better-sqlite3');
const path = require('path');

const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

const db = new Database('status.db');

// 初始化数据库
db.exec(`
  CREATE TABLE IF NOT EXISTS nodes (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT UNIQUE NOT NULL,
    secret TEXT NOT NULL,
    last_seen INTEGER,
    created_at INTEGER DEFAULT (strftime('%s', 'now'))
  );
  
  CREATE TABLE IF NOT EXISTS stats (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    node_id INTEGER,
    cpu REAL,
    mem_used INTEGER,
    mem_total INTEGER,
    disk_used INTEGER,
    disk_total INTEGER,
    net_in INTEGER,
    net_out INTEGER,
    uptime INTEGER,
    load1 REAL,
    load5 REAL,
    load15 REAL,
    ts INTEGER DEFAULT (strftime('%s', 'now')),
    FOREIGN KEY (node_id) REFERENCES nodes(id)
  );
`);

// 生成密钥
function genSecret() {
  return Math.random().toString(36).substr(2, 16);
}

// API: 获取所有节点状态
app.get('/api/nodes', (req, res) => {
  const nodes = db.prepare(`
    SELECT n.*, s.* 
    FROM nodes n 
    LEFT JOIN stats s ON n.id = s.node_id 
    AND s.ts = (SELECT MAX(ts) FROM stats WHERE node_id = n.id)
  `).all();
  res.json(nodes);
});

// API: 添加节点
app.post('/api/nodes', express.json(), (req, res) => {
  const { name } = req.body;
  if (!name) return res.status(400).json({ error: 'name required' });
  
  const secret = genSecret();
  try {
    const result = db.prepare('INSERT INTO nodes (name, secret) VALUES (?, ?)').run(name, secret);
    res.json({ id: result.lastInsertRowid, name, secret });
  } catch (e) {
    res.status(400).json({ error: 'name exists' });
  }
});

// API: 删除节点
app.delete('/api/nodes/:id', (req, res) => {
  db.prepare('DELETE FROM nodes WHERE id = ?').run(req.params.id);
  db.prepare('DELETE FROM stats WHERE node_id = ?').run(req.params.id);
  res.json({ ok: true });
});

// Agent 上报接口
app.post('/report', express.json(), (req, res) => {
  const { secret, cpu, mem_used, mem_total, disk_used, disk_total, net_in, net_out, uptime, load1, load5, load15 } = req.body;
  
  const node = db.prepare('SELECT * FROM nodes WHERE secret = ?').get(secret);
  if (!node) return res.status(403).json({ error: 'invalid secret' });
  
  const now = Math.floor(Date.now() / 1000);
  db.prepare('UPDATE nodes SET last_seen = ? WHERE id = ?').run(now, node.id);
  
  db.prepare(`
    INSERT INTO stats (node_id, cpu, mem_used, mem_total, disk_used, disk_total, net_in, net_out, uptime, load1, load5, load15)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `).run(node.id, cpu, mem_used, mem_total, disk_used, disk_total, net_in, net_out, uptime, load1, load5, load15);
  
  // 清理7天前的数据
  db.prepare('DELETE FROM stats WHERE ts < ?').run(now - 86400 * 7);
  
  // WebSocket 广播
  broadcast({ type: 'update', node_id: node.id, data: req.body });
  
  res.json({ ok: true });
});

// WebSocket 广播
function broadcast(data) {
  const msg = JSON.stringify(data);
  wss.clients.forEach(client => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(msg);
    }
  });
}

// Agent 脚本下载
app.get('/agent.sh', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'agent.sh'));
});

// 静态文件
app.use(express.static(path.join(__dirname, 'public')));

// 首页
app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

const PORT = process.env.PORT || 3800;
server.listen(PORT, () => {
  console.log(`Status panel running on http://0.0.0.0:${PORT}`);
});
