#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""PULSE Wrapper - Orchestrator Lifecycle Management.

Extracted from pulse_wrapper.py (Separation of Concerns refactor, 2026-02-19).
Manages background orchestrator process lifecycle: check, start, ensure-running.
"""
from __future__ import annotations

import os
import subprocess
import sys
import time
from pathlib import Path

SCRIPT_DIR = Path(__file__).resolve().parent
ROOT_DIR = SCRIPT_DIR.parent.parent
STATE_DIR = ROOT_DIR / "state"
ORCHESTRATOR_PID = STATE_DIR / "pulse_orchestrator.pid"
PULSE_SCRIPT = ROOT_DIR / "pulse" / "daemons" / "orchestrator" / "core.py"

# When run directly, ensure pulse package is importable
if str(ROOT_DIR) not in sys.path:
    sys.path.insert(0, str(ROOT_DIR))


def _is_process_running(pid: int) -> bool:
    """Check if a process with the given PID is running (cross-platform)."""
    if os.name == 'nt':
        try:
            output = subprocess.check_output(
                ["tasklist", "/FI", f"PID eq {pid}"],
                stderr=subprocess.STDOUT, creationflags=0x08000000).decode()
            return str(pid) in output
        except Exception:
            return False
    else:
        try:
            os.kill(pid, 0)
        except OSError:
            return False
        return True


def _start_orchestrator():
    """Launch the PULSE orchestrator daemon (pulse.py) in the background."""
    if not PULSE_SCRIPT.exists():
        return
    env = os.environ.copy()
    args = [sys.executable, str(PULSE_SCRIPT)]
    creationflags = getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
    popen_kwargs = {"stdout": subprocess.DEVNULL, "stderr": subprocess.DEVNULL, "env": env}
    if creationflags:
        popen_kwargs["creationflags"] = creationflags
    if os.name != "nt":
        popen_kwargs["start_new_session"] = True
    subprocess.Popen(args, **popen_kwargs)
    for _ in range(8):
        if ORCHESTRATOR_PID.exists():
            break
        time.sleep(0.1)


def _ensure_orchestrator_running():
    """Check if orchestrator is running; if not, start it."""
    if ORCHESTRATOR_PID.exists():
        try:
            pid = int(ORCHESTRATOR_PID.read_text())
        except Exception:
            pid = None
        if pid and _is_process_running(pid):
            return
        ORCHESTRATOR_PID.unlink(missing_ok=True)
    # Kill orphan daemons from crashed session before starting new orchestrator
    try:
        from pulse.daemons.orchestrator.lifecycle import _kill_orphan_daemons
        _kill_orphan_daemons()
    except Exception:
        pass
    print("[PULSE] Starting orchestrator in background...")
    _start_orchestrator()
