using System.Text;
namespace AyCode.Core.Benchmarks.Reporting;
///
/// Context bundle for the unified benchmark report writer. Same record on both sides (Console / BDN),
/// only the differs ("Console" / "Bdn") — that drives the filename prefix
/// (e.g. Console.FullBenchmark_Release_{timestamp}.LLM vs Bdn.FullBenchmark_Release_{timestamp}.LLM).
/// The resolution walks up from to the
/// nearest AyCode.Core.sln and combines with Test_Benchmark_Results\Benchmark — works across
/// build modes (Debug / Release / AOT publish) and worktrees (each worktree has its own .sln, so its bench
/// results land alongside its code).
///
public sealed record ReportingContext(
string SourceTag,
string ResultsDirectory,
string BuildConfiguration,
UTF8Encoding Utf8NoBom)
{
///
/// Resolves the canonical by walking up from
/// to the nearest AyCode.Core.sln, then combining
/// with Test_Benchmark_Results\Benchmark. The build configuration is supplied by the caller
/// (Console resolves via #if AYCODE_NATIVEAOT|DEBUG|else Release; BDN-side currently mirrors
/// the JIT vs AOT discriminator from ).
///
public static ReportingContext Create(string sourceTag, string buildConfiguration) =>
new(sourceTag, ResolveResultsDirectory(), buildConfiguration, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
///
/// Walk-up from the assembly's BaseDirectory to find the repo root (marker: AyCode.Core.sln).
/// Returns {repoRoot}\Test_Benchmark_Results\Benchmark. Worktree-aware: if running from a
/// worktree, the walk finds the worktree's own .sln (each worktree has its own checkout), so
/// results land in the worktree's results folder — the natural place when the worktree's code
/// changes are what produced the numbers.
///
private static string ResolveResultsDirectory()
{
var dir = new DirectoryInfo(AppContext.BaseDirectory);
while (dir != null && !File.Exists(Path.Combine(dir.FullName, "AyCode.Core.sln")))
dir = dir.Parent;
if (dir == null)
throw new InvalidOperationException(
"Cannot locate repo root (AyCode.Core.sln) from AppContext.BaseDirectory: " + AppContext.BaseDirectory);
return Path.Combine(dir.FullName, "Test_Benchmark_Results", "Benchmark");
}
}