"""
Nexa Language — Built-in Benchmarker v24
nexa bench file.nexa --iterations 100 --warmup 10
"""
from __future__ import annotations
import time
import statistics
from typing import List

from .lexer import Lexer
from .parser import Parser
from .interpreter import Interpreter
from .ast_nodes import BenchBlock, TestBlock


def run_benchmarks(source_path: str, iterations: int = 100, warmup: int = 10,
                   output_json: str = None) -> dict:
    """Discover and run all bench {} blocks in a Nexa source file."""
    src = open(source_path, encoding="utf-8").read()
    tokens = Lexer(src).tokenize()
    ast = Parser(tokens).parse()

    benches = [n for n in ast.statements if isinstance(n, BenchBlock)]
    if not benches:
        print("  ⚠️  No bench blocks found. Use: bench \"name\" { ... }")
        return {}

    print(f"\n  ⏱️  Nexa Benchmarker v24")
    print(f"  {'─' * 50}")
    print(f"  Iterations: {iterations}  |  Warmup: {warmup}")
    print(f"  {'─' * 50}")

    results = {}
    for bench in benches:
        interp = Interpreter()
        # Warmup runs
        for _ in range(warmup):
            try:
                interp._exec_block(bench.body, interp._make_global_env())
            except Exception:
                pass

        # Timed runs
        times: List[float] = []
        for _ in range(iterations):
            t0 = time.perf_counter()
            try:
                interp._exec_block(bench.body, interp._make_global_env())
            except Exception:
                pass
            times.append((time.perf_counter() - t0) * 1000)  # ms

        avg   = statistics.mean(times)
        mn    = min(times)
        mx    = max(times)
        stdev = statistics.stdev(times) if len(times) > 1 else 0.0
        ops   = 1000 / avg if avg > 0 else float("inf")

        # Normalized bar (max 30 chars)
        max_in_batch = max(b.get("avg", avg) for b in results.values()) if results else avg
        bar_len = int(min(30, (avg / max(max_in_batch, avg)) * 30))
        bar = "█" * bar_len + "░" * (30 - bar_len)

        print(f"\n  📊 {bench.name}")
        print(f"     {bar}")
        print(f"     avg {avg:.3f}ms  min {mn:.3f}ms  max {mx:.3f}ms  ±{stdev:.3f}ms")
        print(f"     {ops:,.0f} ops/sec")

        results[bench.name] = {"avg": avg, "min": mn, "max": mx, "stdev": stdev,
                               "ops_per_sec": ops, "iterations": iterations}

    print(f"\n  {'─' * 50}")
    print(f"  ✅ Benchmarked {len(results)} block(s)")

    if output_json:
        import json
        with open(output_json, "w", encoding="utf-8") as f:
            json.dump(results, f, indent=2)
        print(f"  📄 Results saved → {output_json}")

    return results
