const express = require('express');
const http = require('http');
const path = require('path');
const cors = require('cors');
const ioModule = require('./io');
const DataService = require('./services/data');
const { jsonStringifyUnicode } = require('./services/unicode-json');

const app = express();
const server = http.createServer(app);

// Initialize Socket.IO
const io = ioModule.init(server);

app.use(express.json());
app.use(cors());

app.use((req, res, next) => {
  const origJson = res.json.bind(res);
  res.json = (data) => {
    if (data === undefined) return origJson(data);
    const body = jsonStringifyUnicode(data);
    res.set('Content-Type', 'application/json; charset=utf-8');
    return res.send(body);
  };
  next();
});

// Mount API Routes
app.use('/api/public', require('./routes/public'));
app.use('/api/files', require('./routes/files'));
app.use('/api/assets', require('./routes/assets'));
app.use('/api', require('./routes/api'));

// Serve Audio Files Statically
const AUDIO_DIR = path.join(__dirname, '../Audio');
app.use('/audio', express.static(AUDIO_DIR));

const ASSETS_DIR = path.join(__dirname, '../Assets');
app.use('/assets', express.static(ASSETS_DIR));

// Serve Lua Scripts
const ROOT_DIR = path.join(__dirname, '..');
app.get('/scripts/:name', (req, res) => {
  const name = req.params.name;
  if (!name.match(/^[a-zA-Z0-9_]+\.lua$/)) return res.status(400).send('Invalid script name');
  const allowed = ['gate.lua', 'ticketmachine.lua', 'startup.lua', 'install_gate.lua', 'install_machine.lua', 'update_gate.lua', 'update_machine.lua', 'server.lua', 'installer.lua', 'installer_bi.lua'];
  if (!allowed.includes(name)) return res.status(404).send('Script not found');
  res.sendFile(path.join(ROOT_DIR, name));
});

// Serve Static Files
const WEB_DIR = path.join(__dirname, '../web');

// Path Routing for single domain
app.get('/', (req, res, next) => {
  const host = req.hostname;
  console.log(`[Router] Accessing / with host: ${host}`);
  
  if (host === 'ticket.fse-media.group' || !host.includes('fse-media.group')) {
    return res.sendFile(path.join(WEB_DIR, 'home.html'));
  }
  next();
});

app.get('/order', (req, res) => res.sendFile(path.join(WEB_DIR, 'ticket-order.html')));
app.get('/search', (req, res) => res.sendFile(path.join(WEB_DIR, 'ticket-search.html')));
app.get('/ic-card/search', (req, res) => res.sendFile(path.join(WEB_DIR, 'ic-card-search.html')));
app.get('/ic-card/order', (req, res) => res.sendFile(path.join(WEB_DIR, 'ic-card-order.html')));
app.get('/ic/:card_id', (req, res) => res.sendFile(path.join(WEB_DIR, 'ic-card-detail.html')));
app.get('/token', (req, res) => res.sendFile(path.join(WEB_DIR, 'token.html')));
app.get('/admin', (req, res) => res.sendFile(path.join(WEB_DIR, 'index.html')));
app.get('/admin/ic-card', (req, res) => res.redirect('/admin?view=iccards'));
app.get('/route', (req, res) => res.sendFile(path.join(WEB_DIR, 'ticket-route.html')));

app.use('/', express.static(WEB_DIR));

// Fallback for static routes (ticket-search, ticket-order) - Legacy support
app.get('/ticket-search/:id', (req, res) => { res.sendFile(path.join(WEB_DIR, 'ticket-search.html')); });
app.get('/ticket-search', (req, res) => { res.sendFile(path.join(WEB_DIR, 'ticket-search.html')); });
app.get('/ticket-order', (req, res) => { res.sendFile(path.join(WEB_DIR, 'ticket-order.html')); });
app.get('/ic-card-admin', (req, res) => { res.redirect('/admin?view=iccards'); });
app.get('/ic-card-search', (req, res) => { res.sendFile(path.join(WEB_DIR, 'ic-card-search.html')); });
app.get('/ic-card-order', (req, res) => { res.sendFile(path.join(WEB_DIR, 'ic-card-order.html')); });

// Ticket Board
// Handles ticket.fse-media.group/detail/TicketID
app.get('/detail/:ticket_id', (req, res, next) => {
  const id = req.params.ticket_id;
  // If it's a known static file extension, let express.static handle it
  if (id.includes('.')) return next();
  
  return res.sendFile(path.join(WEB_DIR, 'ticket-board.html'));
});

// Start Server
const PORT = process.env.PORT || 23333;
const HOST = process.env.HOST || '0.0.0.0';

(async () => {
  await DataService.init();

  // Start periodic export
  // setInterval(DataService.saveExport, 10000);

  // Global Error Handler
  app.use((err, req, res, next) => {
    console.error(err.stack);
    try {
      DataService.appendLog({
        ts: new Date().toISOString(),
        ip: (req.headers['x-forwarded-for'] || '').toString().split(',')[0].trim() || req.ip || req.connection?.remoteAddress || '',
        ua: String(req.headers['user-agent'] || ''),
        method: req.method,
        path: req.originalUrl || req.path || '',
        category: 'system',
        level: 'error',
        type: 'unhandled_error',
        detail: { error: err?.message || String(err) }
      });
    } catch (e) {}
    res.status(500).json({ ok: false, error: 'Internal Server Error' });
  });

  server.listen(PORT, HOST, () => {
    console.log(`ftc admin server running at http://${HOST}:${PORT}/`);
  });
})();
