/**
 * 生产模式下的服务器入口
 * 使用 NODE_ENV=production node production.js 来启动
 */
process.env.NODE_ENV = 'production';

const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const path = require('path');
const http = require('http');
const { createWebSocketServer } = require('./websocket');

// 调用 generate-manifest.js 生成 manifest.json
function generateManifest() {
  console.log('Generating manifest.json for Docker deployment...');

  try {
    const generateManifestScript = path.join(
      __dirname,
      'scripts',
      'generate-manifest.js'
    );
    require(generateManifestScript);
  } catch (error) {
    console.error('❌ Error calling generate-manifest.js:', error);
    throw error;
  }
}

// 生成manifest
generateManifest();

const hostname = process.env.HOSTNAME || '0.0.0.0';
const port = process.env.PORT || 3000;

// 在生产模式下初始化 Next.js
const app = next({
  dev: false,
  hostname,
  port
});

const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = createServer(async (req, res) => {
    try {
      // 检查是否是WebSocket升级请求，如果是则跳过Next.js处理
      const upgrade = req.headers.upgrade;
      if (upgrade && upgrade.toLowerCase() === 'websocket') {
        // 不处理WebSocket升级请求，让upgrade事件处理器处理
        return;
      }

      // 使用Next.js处理所有非WebSocket请求
      const parsedUrl = parse(req.url, true);
      await handle(req, res, parsedUrl);
    } catch (err) {
      console.error('处理请求时出错:', req.url, err);
      res.statusCode = 500;
      res.end('内部服务器错误');
    }
  });

  // 初始化 WebSocket 服务器
  const wss = createWebSocketServer();

  // 将 WebSocket 服务器实例存储到全局对象中，供 API 路由使用
  global.wss = wss;

  // 使用WeakSet来跟踪已处理的socket，避免重复处理
  const handledSockets = new WeakSet();

  // 处理 WebSocket 升级请求
  server.on('upgrade', (request, socket, head) => {
    // 如果socket已经被处理过，直接返回
    if (handledSockets.has(socket)) {
      return;
    }

    const pathname = parse(request.url).pathname;

    if (pathname === '/ws') {
      console.log('处理 WebSocket 升级请求:', pathname);

      // 标记socket已被处理
      handledSockets.add(socket);

      // 处理WebSocket连接
      try {
        wss.handleUpgrade(request, socket, head, (ws) => {
          wss.emit('connection', ws, request);
        });
      } catch (error) {
        console.error('WebSocket升级错误:', error);
        socket.destroy();
      }
    } else {
      console.log('未知的升级请求路径:', pathname);
      // 不销毁socket，让它自然关闭
    }
  });

  // 启动服务器
  server.listen(port, (err) => {
    if (err) throw err;
    console.log(`> 服务已启动 (生产模式): http://${hostname}:${port}`);
    console.log(`> WebSocket 服务已启动: ws://${hostname}:${port}/ws`);

    // 设置服务器启动后的任务
    setupServerTasks();
  });
});

// 设置服务器启动后的任务
function setupServerTasks() {
  // 每 1 秒轮询一次，直到请求成功
  const TARGET_URL = `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000}/login`;

  const intervalId = setInterval(() => {
    console.log(`Fetching ${TARGET_URL} ...`);

    const req = http.get(TARGET_URL, (res) => {
      // 当返回 2xx 状态码时认为成功，然后停止轮询
      if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
        console.log('Server is up, stop polling.');
        clearInterval(intervalId);

        setTimeout(() => {
          // 服务器启动后，立即执行一次 cron 任务
          executeCronJob();
        }, 3000);

        // 然后设置每小时执行一次 cron 任务
        setInterval(() => {
          executeCronJob();
        }, 60 * 60 * 1000); // 每小时执行一次
      }
    });

    req.setTimeout(2000, () => {
      req.destroy();
    });
  }, 1000);
}

// 执行 cron 任务的函数
function executeCronJob() {
  const cronUrl = `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000}/api/cron`;

  console.log(`Executing cron job: ${cronUrl}`);

  const req = http.get(cronUrl, (res) => {
    let data = '';

    res.on('data', (chunk) => {
      data += chunk;
    });

    res.on('end', () => {
      if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
        console.log('Cron job executed successfully:', data);
      } else {
        console.error('Cron job failed:', res.statusCode, data);
      }
    });
  });

  req.on('error', (err) => {
    console.error('Error executing cron job:', err);
  });

  req.setTimeout(30000, () => {
    console.error('Cron job timeout');
    req.destroy();
  });
}
