const path = require('path');
const { Client } = require('../../backend/node_modules/pg');
const {
  config,
  ensureDir,
  executeMeasured,
  getDbConfig,
  loadQueries,
  resultsDir,
  summarizeRows,
  writeCsv,
  writeJson
} = require('./benchmark-lib');

const levels = String(process.env.BENCHMARK_CONCURRENCY_LEVELS || config.concurrencyLevels.join(','))
  .split(',')
  .map((item) => Number.parseInt(item.trim(), 10))
  .filter((item) => Number.isFinite(item) && item > 0);
const requestsPerLevel = Number.parseInt(
  process.env.BENCHMARK_CONCURRENCY_REQUESTS || config.concurrencyRequestsPerLevel,
  10
);

const runPool = async (items, workers, task) => {
  let index = 0;
  const worker = async () => {
    while (index < items.length) {
      const current = items[index];
      index += 1;
      await task(current);
    }
  };
  await Promise.all(Array.from({ length: Math.min(workers, items.length) }, () => worker()));
};

const main = async () => {
  ensureDir(resultsDir);
  const queries = loadQueries();
  const raw = [];

  for (const level of levels) {
    const work = Array.from({ length: requestsPerLevel }, (_, index) => ({
      query: queries[index % queries.length],
      repetition: index + 1
    }));
    await runPool(work, level, async ({ query, repetition }) => {
      const client = new Client(getDbConfig(level));
      await client.connect();
      try {
        const row = await executeMeasured(client, query, repetition, 'concurrency', level);
        raw.push(row);
        process.stdout.write(`concurrency=${level} ${query.id} ${repetition}/${requestsPerLevel} ${row.success ? 'ok' : 'fail'} ${row.endpoint_total_ms.toFixed(2)}ms\n`);
      } finally {
        await client.end();
      }
    });
  }

  raw.sort((a, b) => a.concurrency_level - b.concurrency_level || a.repetition - b.repetition);
  const summary = summarizeRows(raw, ['phase', 'concurrency_level', 'query_id', 'query_name', 'query_group']);
  const byLevel = summarizeRows(raw, ['phase', 'concurrency_level']);
  writeCsv(path.join(resultsDir, 'concurrency_raw.csv'), raw);
  writeCsv(path.join(resultsDir, 'concurrency_summary.csv'), summary.concat(byLevel));
  writeJson(path.join(resultsDir, 'concurrency.json'), {
    generatedAt: new Date().toISOString(),
    levels,
    requestsPerLevel,
    expectedMeasuredOperations: levels.length * requestsPerLevel,
    measuredOperations: raw.length,
    summary,
    byLevel
  });
};

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
