import fs from 'node:fs';

function parseArgs(argv) {
  const args = new Map();
  for (let i = 2; i < argv.length; i++) {
    const value = argv[i];
    if (!value.startsWith('--')) continue;
    const [key, inline] = value.slice(2).split('=');
    if (inline !== undefined) {
      args.set(key, inline);
      continue;
    }
    const next = argv[i + 1];
    if (next && !next.startsWith('--')) {
      args.set(key, next);
      i++;
    } else {
      args.set(key, true);
    }
  }
  return args;
}

function parseCsv(content) {
  const lines = content.split('\n').map(line => line.trim()).filter(Boolean);
  const data = [];
  for (const line of lines) {
    if (line.startsWith('b2c_auth_bench')) continue;
    if (line.startsWith('scenario,')) continue;
    const parts = line.split(',');
    if (parts.length < 11) continue;
    const [scenario, nodes, edges, buildMs, authMs, authQps, precision, recall, f1, p95, p99] = parts;
    data.push({
      scenario,
      nodes: Number(nodes),
      edges: Number(edges),
      buildMs: Number(buildMs),
      authMs: Number(authMs),
      authQps: Number(authQps),
      precision: Number(precision),
      recall: Number(recall),
      f1: Number(f1),
      p95: Number(p95),
      p99: Number(p99)
    });
  }
  return data;
}

function fitPowerLaw(points, field) {
  const samples = points.filter(point => point[field] > 0 && point.nodes > 0);
  if (samples.length < 2) return null;
  const xs = samples.map(point => Math.log(point.nodes));
  const ys = samples.map(point => Math.log(point[field]));
  const n = xs.length;
  const sumX = xs.reduce((acc, value) => acc + value, 0);
  const sumY = ys.reduce((acc, value) => acc + value, 0);
  const sumXY = xs.reduce((acc, value, index) => acc + value * ys[index], 0);
  const sumX2 = xs.reduce((acc, value) => acc + value * value, 0);
  const denom = n * sumX2 - sumX * sumX;
  if (denom === 0) return null;
  const slope = (n * sumXY - sumX * sumY) / denom;
  const intercept = (sumY - slope * sumX) / n;
  return { slope, intercept };
}

function predictPowerLaw(model, nodes) {
  return Math.exp(model.intercept + model.slope * Math.log(nodes));
}

const args = parseArgs(process.argv);
const inputPath = args.get('input') || 'new-eval/b2c-auth-bench-output.txt';
const content = fs.readFileSync(inputPath, 'utf8');
const data = parseCsv(content);
const targetNodes = Number(args.get('target') || 1_000_000);

const grouped = new Map();
for (const row of data) {
  if (!grouped.has(row.scenario)) {
    grouped.set(row.scenario, []);
  }
  grouped.get(row.scenario).push(row);
}

const metrics = ['edges', 'buildMs', 'authMs', 'authQps', 'p95', 'p99'];
console.log('b2c_auth_fit');
console.log(`target_nodes=${targetNodes}`);
console.log('scenario,metric,model,predicted');

for (const [scenario, points] of grouped.entries()) {
  for (const metric of metrics) {
    const model = fitPowerLaw(points, metric);
    if (!model) continue;
    const predicted = predictPowerLaw(model, targetNodes);
    const modelLabel = `${Math.exp(model.intercept).toFixed(6)} * n^${model.slope.toFixed(3)}`;
    console.log([
      scenario,
      metric,
      modelLabel,
      predicted.toFixed(3)
    ].join(','));
  }
}
