/**
 * R4 — per-project metrics reset (24a) across a NEW project compile and an
 * epoch continuation; App.tsx epoch view labels per-epoch vs project-cumulative.
 *
 * Prefer test over App edits: labels already ship in web/src/App.tsx — this
 * file pins the contract + the selectTier1StatusMetrics reset behavior.
 */
import { describe, expect, it } from 'vitest';
import fs from 'node:fs';
import path from 'node:path';
import { selectTier1StatusMetrics } from '../src/tier1/metricsHelpers';
import { aggregateProjectStats, type RunRecordLike } from '../src/tier1/statsAggregate';

function rec(partial: RunRecordLike): RunRecordLike {
  return {
    id: partial.id ?? 'r1',
    ts: partial.ts ?? '2026-07-26T12:00:00.000Z',
    mode: partial.mode ?? 'rha',
    problems: partial.problems ?? 0,
    error: partial.error ?? null,
    metrics: partial.metrics ?? {},
    cost: partial.cost,
    ...partial,
  };
}

describe('R4 per-project metrics reset (24a)', () => {
  it('NEW project compile: running status surfaces fresh live zeros, not a prior project\'s stored metrics', () => {
    const priorProjectStored = { tokensIn: 9000, tokensOut: 4000, llmCalls: 55 };
    const freshLive = { tokensIn: 0, tokensOut: 0, llmCalls: 0 };
    // New project compile just started — stored may still hold leftovers from
    // another project in the same offscreen doc until overwrite completes.
    expect(selectTier1StatusMetrics({
      running: true,
      stored: priorProjectStored,
      live: freshLive,
    })).toEqual(freshLive);
  });

  it('epoch continuation: running status surfaces fresh live zeros, not the prior epoch\'s stored metrics', () => {
    const priorEpochStored = { tokensIn: 1200, tokensOut: 800, llmCalls: 12 };
    const continuationLive = { tokensIn: 0, tokensOut: 0, llmCalls: 0 };
    expect(selectTier1StatusMetrics({
      running: true,
      stored: priorEpochStored,
      live: continuationLive,
    })).toEqual(continuationLive);
    // After the continuation finishes, stored (this epoch's final) wins again.
    const finishedContinuation = { tokensIn: 300, tokensOut: 100, llmCalls: 3 };
    expect(selectTier1StatusMetrics({
      running: false,
      stored: finishedContinuation,
      live: continuationLive,
    })).toEqual(finishedContinuation);
  });

  it('project-cumulative scope still sums every epoch in the project', () => {
    const runs: RunRecordLike[] = [
      rec({
        id: 'root', ts: '2026-07-26T10:00:00.000Z', projectId: 'root',
        metrics: { tokensIn: 100, tokensOut: 50, llmCalls: 2 },
      }),
      rec({
        id: 'ep2', ts: '2026-07-26T11:00:00.000Z', projectId: 'root',
        metrics: { tokensIn: 40, tokensOut: 20, llmCalls: 1 },
      }),
    ];
    const summary = aggregateProjectStats(runs, 'root');
    expect(summary.totalsRuns).toBe(2);
    expect(summary.facets.tokensTotal.lifetime).toBe(210);
  });
});

describe('R4 App.tsx epoch vs project-cumulative labels', () => {
  it('labels per-epoch run metrics and project-cumulative scope explicitly', () => {
    const src = fs.readFileSync(path.resolve('web/src/App.tsx'), 'utf8');
    // Per-epoch (resets every compile — not summed across prior epochs).
    expect(src).toContain('this epoch');
    expect(src).toContain(
      'Resets to zero at the start of every compile — this project\'s prior epochs are not summed in here',
    );
    // Project-cumulative (alongside global install scope).
    expect(src).toContain('this project');
    expect(src).toContain("lifetime: 'Project total'");
    expect(src).toContain('Project &amp; install metrics');
  });
});
