using System.Text;

namespace AyCode.Core.Benchmarks.Reporting;

/// <summary>
/// Context bundle for the unified benchmark report writer. Same record on both sides (Console / BDN),
/// the <see cref="SourceTag"/> differs ("Console" / "Bdn") and drives the filename prefix
/// (e.g. <c>Console.FullBenchmark_Release_{timestamp}.LLM</c> vs <c>Bdn.FullBenchmark_Release_{timestamp}.LLM</c>).
/// The <see cref="ResultsDirectory"/> resolution walks up from <see cref="AppContext.BaseDirectory"/> to the
/// nearest <c>AyCode.Core.sln</c> and combines with <c>Test_Benchmark_Results\Benchmark</c> — works across
/// build modes (Debug / Release / AOT publish) and worktrees (each worktree has its own .sln, so its bench
/// results land alongside its code). The remaining fields capture run-header information (charset, iter
/// counts, target sample window, CV threshold) so the writer can render a self-documenting header in both
/// the <c>.log</c> and <c>.LLM</c> outputs.
/// </summary>
public sealed record ReportingContext(
    string SourceTag,
    string ResultsDirectory,
    string BuildConfiguration,
    UTF8Encoding Utf8NoBom,
    string CharsetName,
    int WarmupIterations,
    int BenchmarkSamples,
    int TargetSampleMs,
    double UnstableCVThreshold,
    double MicroOptCVThreshold)
{
    /// <summary>
    /// Walks up from the assembly's BaseDirectory to find the repo root (marker: <c>AyCode.Core.sln</c>).
    /// Returns <c>{repoRoot}\Test_Benchmark_Results\Benchmark</c>. 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.
    /// </summary>
    public 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");
    }
}
