'use strict';

const express = require('express');
const rateLimit = require('express-rate-limit');
const { Bot } = require('../bot/bot');
const { ProxyLease } = require('../proxy/lease');

function buildTestRoutes(opts) {
  const { cfg, state, proxyRegistry, logger, eventBus, validateStart, rateLimits } = opts;
  const router = express.Router();

  const testStartLimiter = rateLimit({
    windowMs: 60 * 1000,
    max: rateLimits?.test_start_per_min || 10,
    standardHeaders: true,
    legacyHeaders: false,
    handler: (req, res) => res.status(429).json({ error: 'Too many test starts. Slow down.' }),
  });

  function randomUsername(prefix) {
    const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    let suffix = '';
    for (let i = 0; i < 6; i++) suffix += chars[Math.floor(Math.random() * chars.length)];
    return `${prefix}${suffix}`;
  }

  async function launchTest({ target, botCount, prefix, delay, password, messages, stayConnected, strategy }) {
    if (state.testRunning && state.activeBots.size === 0) state.testRunning = false;
    if (state.testRunning) {
      logger.warn('Test already running.');
      return { ok: false, reason: 'Test already running' };
    }
    state.testRunning = true;
    state.currentTarget = target;
    state.currentBotPassword = password;
    state.currentChatMessages = messages;
    state.currentStayConnected = !!stayConnected;
    state.currentProxyStrategy = strategy || null;

    const aliveProxies = proxyRegistry.list({ status: 'alive' }).length;
    logger.info(`═══ Starting load test ═══`);
    logger.info(`Target: ${target} | Bots: ${botCount} | Delay: ${delay}ms | Strategy: ${strategy || proxyRegistry.defaultStrategy}`);
    logger.info(`Protocol: MC 1.12.2 (340) | Password: ${password}`);
    logger.info(`Proxies: ${aliveProxies} alive`);

    state.proxyLease = new ProxyLease(proxyRegistry, { strategy: state.currentProxyStrategy });

    for (let i = 0; i < botCount; i++) {
      if (!state.testRunning) break;
      const username = randomUsername(prefix);
      const proxy = state.proxyLease.pick();
      const bot = new Bot({
        id: `bot_${++state.counters.totalBotsSpawned}`,
        username,
        targetUrl: target,
        password,
        proxy: proxy ? { type: proxy.type, host: proxy.host, port: proxy.port, key: proxy.key } : null,
        config: cfg.bots,
        chatMessages: messages,
        stayConnected,
        log: (level, msg) => logger[level] ? logger[level](msg) : logger.info(msg),
        eventBus,
      });
      state.addBot(bot);
      if (delay > 0 && i < botCount - 1) {
        await new Promise(r => setTimeout(r, delay));
      }
      bot.start();
    }
    logger.success(`Spawned ${state.activeBots.size} bots.`);
    return { ok: true };
  }

  router.post('/start', testStartLimiter, async (req, res) => {
    const validation = validateStart(req.body);
    if (!validation.ok) return res.status(400).json({ error: validation.error });
    const { target, bots, usernamePrefix, spawnDelay, botPassword, chatMessages, stayConnected, proxyStrategy } = req.body;
    const botCount = Math.min(Math.max(parseInt(bots, 10) || 10, 1), cfg.bots.max_bots);
    const delay = Math.max(0, Math.min(parseInt(spawnDelay, 10) || 0, cfg.bots.max_spawn_delay));
    const prefix = usernamePrefix || 'TestBot';
    const pwd = botPassword || cfg.bots.password;
    const messages = chatMessages !== undefined
      ? (typeof chatMessages === 'string'
          ? chatMessages.split('\n').map(l => l.trim()).filter(Boolean)
          : Array.isArray(chatMessages) ? chatMessages : [])
      : cfg.bots.chat_messages || [];

    const result = await launchTest({
      target, botCount, prefix, delay, password: pwd,
      messages, stayConnected: !!stayConnected, strategy: proxyStrategy || null,
    });
    if (!result.ok) return res.status(409).json({ error: result.reason });
    res.json({ success: true });
  });

  router.post('/stop', (req, res) => {
    state.testRunning = false;
    if (state.proxyLease) {
      state.proxyLease.returnAll();
      state.proxyLease = null;
    }
    logger.info(`Stopping all bots (${state.activeBots.size})...`);
    let n = 0;
    for (const b of state.activeBots.values()) { b.stop('test-stop'); n++; }
    logger.success('All bots stopped.');
    res.json({ success: true, stopped: n });
  });

  router.post('/reset', (req, res) => {
    state.testRunning = false;
    state.clearLogs();
    if (state.proxyLease) {
      state.proxyLease.returnAll();
      state.proxyLease = null;
    }
    logger.info('State reset.');
    res.json({ success: true });
  });

  router.get('/quick-commands', (req, res) => {
    res.json({ commands: cfg.quick_commands || [] });
  });

  router.get('/strategies', (req, res) => {
    res.json({ default: proxyRegistry.defaultStrategy, available: ['random', 'round-robin', 'least-used', 'best-score'] });
  });

  return router;
}

module.exports = { buildTestRoutes };
