"""Meta-generator: Performance self-introspection examples.

Generates examples that benchmark bencher's own overhead, enabling
performance tracking across commits via the documentation gallery.
"""

import inspect
import bencher as bn
from bencher.example.example_self_benchmark import BencherSelfBenchmark, TrivialWorkload
from bencher.example.meta.meta_generator_base import MetaGeneratorBase

OUTPUT_DIR = "performance"

PERFORMANCE_EXAMPLES = [
    "perf_self_benchmark",
    "perf_self_benchmark_over_time",
]


class MetaPerformance(MetaGeneratorBase):
    """Generate Python examples for bencher self-introspection."""

    example = bn.StringSweep(PERFORMANCE_EXAMPLES, doc="Which performance example to generate")

    def benchmark(self):
        if self.example == "perf_self_benchmark":
            self._generate_self_benchmark()
        elif self.example == "perf_self_benchmark_over_time":
            self._generate_self_benchmark_over_time()

    def _generate_self_benchmark(self):
        """Generate the self-benchmark example."""
        imports = "import bencher as bn"

        body = """\
bench = BencherSelfBenchmark().to_bench(run_cfg)
bench.plot_sweep(
    input_vars=["num_samples"],
    result_vars=["total_ms", "dataset_setup_ms", "job_submission_ms", "job_execution_ms"],
    title="Phase Timing vs Problem Size",
)
bench.plot_sweep(
    input_vars=["num_samples"],
    result_vars=["throughput"],
    title="Throughput vs Problem Size",
)
bench.plot_sweep(
    input_vars=["num_samples", "use_cache"],
    result_vars=["total_ms"],
    title="Cache Impact on Total Time",
)
"""

        self.generate_example(
            title="Bencher self-introspection: overhead vs problem size",
            output_dir=OUTPUT_DIR,
            filename="perf_self_benchmark",
            function_name="example_perf_self_benchmark",
            imports=imports,
            body=body,
            class_code=_get_shared_class_code(),
        )

    def _generate_self_benchmark_over_time(self):
        """Generate the over-time self-benchmark example."""
        imports = "import bencher as bn"

        body = """\
if run_cfg is None:
    run_cfg = bn.BenchRunCfg()
run_cfg.auto_plot = False
time_src = bn.git_time_event()
bench = BencherSelfBenchmark().to_bench(run_cfg)
bench.plot_sweep(
    input_vars=["num_samples"],
    result_vars=["total_ms", "dataset_setup_ms", "job_submission_ms", "job_execution_ms"],
    title="Overhead Over Time: Phase Timing",
    time_src=time_src,
)
bench.plot_sweep(
    input_vars=["num_samples"],
    result_vars=["throughput"],
    title="Overhead Over Time: Throughput",
    time_src=time_src,
)
"""

        self.generate_example(
            title="Bencher self-introspection: overhead tracked over time",
            output_dir=OUTPUT_DIR,
            filename="perf_self_benchmark_over_time",
            function_name="example_perf_self_benchmark_over_time",
            imports=imports,
            body=body,
            class_code=_get_shared_class_code(),
            run_kwargs={"over_time": True},
        )


def _get_shared_class_code():
    """Extract class source from the canonical module to avoid duplication.

    Falls back to reading the source file directly if inspect.getsource is
    unavailable (e.g. zipapp or compiled distributions).
    """
    try:
        return inspect.getsource(TrivialWorkload) + "\n\n" + inspect.getsource(BencherSelfBenchmark)
    except OSError:
        import importlib.resources

        src = importlib.resources.files("bencher.example").joinpath("example_self_benchmark.py")
        return src.read_text(encoding="utf-8")


def example_meta_performance():
    """Generate all performance self-introspection examples."""
    gen = MetaPerformance()
    for example in PERFORMANCE_EXAMPLES:
        gen(example=example)
