import pytest
import subprocess
import time
import requests
import os
import signal
import sys
import os

# Ensure project root is in path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from api_hook_client import ApiHookClient

def kill_process_tree(pid):
    """Robustly kills a process and all its children."""
    if pid is None:
        return
    try:
        print(f"[Fixture] Attempting to kill process tree for PID {pid}...")
        if os.name == 'nt':
            # /F is force, /T is tree (includes children)
            subprocess.run(["taskkill", "/F", "/T", "/PID", str(pid)], 
                           stdout=subprocess.DEVNULL, 
                           stderr=subprocess.DEVNULL, 
                           check=False)
        else:
            # On Unix, kill the process group
            os.killpg(os.getpgid(pid), signal.SIGKILL)
        print(f"[Fixture] Process tree {pid} killed.")
    except Exception as e:
        print(f"[Fixture] Error killing process tree {pid}: {e}")

@pytest.fixture(scope="session")
def live_gui():
    """
    Session-scoped fixture that starts gui_2.py with --enable-test-hooks.
    """
    gui_script = "gui_2.py"
    print(f"\n[Fixture] Starting {gui_script} --enable-test-hooks...")
    
    os.makedirs("logs", exist_ok=True)
    log_file = open(f"logs/{gui_script.replace('.', '_')}_test.log", "w", encoding="utf-8")

    process = subprocess.Popen(
        ["uv", "run", "python", "-u", gui_script, "--enable-test-hooks"],
        stdout=log_file,
        stderr=log_file,
        text=True,
        creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0
    )

    max_retries = 15  # Slightly more time for gui_2
    ready = False
    print(f"[Fixture] Waiting up to {max_retries}s for Hook Server on port 8999...")
    
    start_time = time.time()
    while time.time() - start_time < max_retries:
        try:
            response = requests.get("http://127.0.0.1:8999/status", timeout=0.5)
            if response.status_code == 200:
                ready = True
                print(f"[Fixture] GUI Hook Server for {gui_script} is ready after {round(time.time() - start_time, 2)}s.")
                break
        except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
            if process.poll() is not None:
                print(f"[Fixture] {gui_script} process died unexpectedly during startup.")
                break
            time.sleep(0.5)
            
    if not ready:
        print(f"[Fixture] TIMEOUT/FAILURE: Hook server for {gui_script} failed to respond.")
        kill_process_tree(process.pid)
        pytest.fail(f"Failed to start {gui_script} with test hooks.")
        
    try:
        yield process, gui_script
    finally:
        print(f"\n[Fixture] Finally block triggered: Shutting down {gui_script}...")
        # Reset the GUI state before shutting down
        try:
            client.reset_session()
            time.sleep(0.5)
        except: pass
        kill_process_tree(process.pid)
        log_file.close()
