#!/usr/bin/env -S uv run --script
"""Profile Lost Pig V8 execution — find performance bottlenecks.

Runs the interpreter under cProfile for a few commands, then reports
the top functions by cumulative time and total time, plus callers of
expensive functions.
"""

# ruff: noqa: E402
import contextlib
import cProfile
import pstats
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root / "src"))

from mudlib.zmachine import ZMachine, zstream, zui
from mudlib.zmachine.trivialzui import TrivialAudio, TrivialFilesystem, TrivialScreen
from mudlib.zmachine.zcpu import ZCpuQuit, ZCpuRestart

story_path = project_root / "content" / "stories" / "LostPig.z8"
if not story_path.exists():
    print(f"ERROR: {story_path} not found")
    sys.exit(1)

story_bytes = story_path.read_bytes()
print(f"Loaded LostPig.z8: {len(story_bytes)} bytes, version {story_bytes[0]}")


class AutoInputStream(zstream.ZInputStream):
    """Input stream that auto-feeds commands then quits."""

    def __init__(self):
        super().__init__()
        self._commands = ["look", "look", "inventory"]
        self._command_index = 0

    def read_line(self, *args, **kwargs):
        if self._command_index >= len(self._commands):
            raise ZCpuQuit
        cmd = self._commands[self._command_index]
        self._command_index += 1
        print(f"> {cmd}")
        return cmd

    def read_char(self, timed_input_routine=None, timed_input_interval=0):
        # Return enter key (13) when read_char is called
        return 13


audio = TrivialAudio()
screen = TrivialScreen()
keyboard = AutoInputStream()
filesystem = TrivialFilesystem()
ui = zui.ZUI(audio, screen, keyboard, filesystem)
zm = ZMachine(story_bytes, ui)

print("Running under cProfile...\n")

profiler = cProfile.Profile()
profiler.enable()

with contextlib.suppress(ZCpuQuit, ZCpuRestart):
    zm.run()

profiler.disable()

print("\n" + "=" * 80)
print("PROFILING RESULTS")
print("=" * 80 + "\n")

# Create stats object
stats = pstats.Stats(profiler)
stats.strip_dirs()
stats.sort_stats("cumulative")

print("TOP 40 FUNCTIONS BY CUMULATIVE TIME:")
print("-" * 80)
stats.print_stats(40)

print("\n" + "=" * 80)
print("TOP 40 FUNCTIONS BY TOTAL TIME:")
print("-" * 80)
stats.sort_stats("time")
stats.print_stats(40)

print("\n" + "=" * 80)
print("TOP 40 CALLERS OF MOST EXPENSIVE FUNCTIONS:")
print("-" * 80)
stats.sort_stats("cumulative")
stats.print_callers(40)

print("\n" + "=" * 80)
print("PROFILING COMPLETE")
print("=" * 80)
