'use strict';

const http = require('http');
const { createApp } = require('../src/server');

async function request(server, opts) {
  return new Promise((resolve, reject) => {
    const port = server.address().port;
    const headers = { ...(opts.headers || {}) };
    if (opts.cookie) headers['Cookie'] = opts.cookie;
    if (opts.body) headers['Content-Type'] = 'application/json';
    const req = http.request({
      hostname: '127.0.0.1',
      port,
      path: opts.path,
      method: opts.method || 'GET',
      headers,
    }, (res) => {
      const chunks = [];
      res.on('data', (c) => chunks.push(c));
      res.on('end', () => {
        const body = Buffer.concat(chunks).toString('utf8');
        let json = null;
        try { json = JSON.parse(body); } catch (_) {}
        resolve({ status: res.statusCode, headers: res.headers, body, json });
      });
    });
    req.on('error', reject);
    if (opts.body) req.write(JSON.stringify(opts.body));
    req.end();
  });
}

function assert(cond, msg) {
  if (!cond) throw new Error('assertion failed: ' + msg);
  process.stdout.write(`  ✓ ${msg}\n`);
}

async function main() {
  const { server, shutdown } = createApp();
  await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
  const port = server.address().port;
  process.stdout.write(`smoke: server listening on 127.0.0.1:${port}\n`);

  try {
    const badLogin = await request(server, { method: 'POST', path: '/api/auth/login', body: { password: 'wrong' } });
    assert(badLogin.status === 401, 'wrong password returns 401');

    const login = await request(server, { method: 'POST', path: '/api/auth/login', body: { password: process.env.SITE_PASSWORD } });
    assert(login.status === 200, 'correct password returns 200');
    assert(login.json && login.json.success === true, 'login response has success: true');
    const cookie = login.headers['set-cookie']?.[0]?.split(';')[0];
    assert(cookie && cookie.startsWith('auth_token='), 'auth_token cookie set');

    const checkAuth = await request(server, { path: '/api/auth/check', cookie });
    assert(checkAuth.json && checkAuth.json.authenticated === true, 'auth check returns authenticated');

    const stats = await request(server, { path: '/api/stats', cookie });
    assert(stats.status === 200, 'GET /api/stats returns 200');
    assert(stats.json && stats.json.activeBots === 0, 'initial activeBots is 0');
    assert(typeof stats.json.totalBotsSpawned === 'number', 'totalBotsSpawned is a number');

    const proxyList = await request(server, { path: '/api/proxy/list', cookie });
    assert(proxyList.status === 200, 'GET /api/proxy/list returns 200');
    assert(proxyList.json && Array.isArray(proxyList.json.proxies), 'proxies is an array');

    const strategies = await request(server, { path: '/api/test/strategies', cookie });
    assert(strategies.status === 200, 'GET /api/test/strategies returns 200');
    assert(strategies.json && Array.isArray(strategies.json.available), 'strategies has available list');

    const badStart = await request(server, {
      method: 'POST', path: '/api/test/start', cookie,
      body: { target: 'not-a-url', bots: 1 },
    });
    assert(badStart.status === 400, 'invalid target returns 400');

    const healthz = await request(server, { path: '/api/healthz' });
    assert(healthz.status === 200, 'GET /api/healthz returns 200');
    assert(healthz.json && healthz.json.status, 'healthz has status');

    const metrics = await request(server, { path: '/api/metrics' });
    assert(metrics.status === 200, 'GET /api/metrics returns 200');
    assert(metrics.body.includes('crackedflooder_bots_active'), 'metrics has crackedflooder_bots_active');

    process.stdout.write('smoke: all checks passed\n');
    shutdown();
    setTimeout(() => process.exit(0), 1000);
  } catch (err) {
    process.stderr.write(`smoke FAILED: ${err.message}\n`);
    shutdown();
    setTimeout(() => process.exit(1), 1000);
  }
}

main();
