#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Helper operations for orchestrator schedulers."""
from __future__ import annotations

import json
import logging
import subprocess
import sys
import threading
import time
from pathlib import Path

log = logging.getLogger("pulse.daemons.orchestrator.scheduler_ops")

def get_effective_interval(scheduler_name: str, default: int, override_file: Path) -> int:
    """Read interval override from D13 homeostatic state."""
    try:
        if override_file.exists():
            data = json.loads(override_file.read_text(encoding="utf-8"))
            return data.get("overrides", {}).get(scheduler_name, default)
        return default
    except (json.JSONDecodeError, OSError):
        return default


def run_script(script: Path, label: str, timeout: int = 120, extra_args: list = None):
    """Run a script as a subprocess, record heartbeat."""
    if not script.exists():
        return
    cmd = [sys.executable, str(script)]
    if extra_args:
        cmd.extend(extra_args)
    exit_code = -1
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout)
        exit_code = result.returncode
        if result.stdout:
            for line in result.stdout.strip().split("\n"):
                print(f"[PULSE] {line}")
        if result.stderr:
            for line in result.stderr.strip().split("\n"):
                print(f"[PULSE] {line}")
    except subprocess.TimeoutExpired as _te:
        print(f"[PULSE] {label} timed out after {timeout}s.")
        exit_code = -2
        try:
            _te.process.kill()
            _te.process.communicate()
        except Exception: pass
    except Exception as e:
        print(f"[PULSE] {label} error: {e}")
    
    try:
        from pulse.daemons.runtime.daemon_heartbeat import send_heartbeat
        hb_name = label.lower().replace(" ", "_").replace("-", "_")
        send_heartbeat(hb_name, status="alive" if exit_code == 0 else "error",
                       metrics={"exit_code": exit_code})
    except Exception: pass


def scheduler_loop(script: Path, label: str, interval: int, running_check, name: str, 
                   initial_delay: int = 0, timeout: int = 120, extra_args: list = None, 
                   run_at_boot: bool = True, override_file: Path = None):
    """Generic scheduler loop."""
    def _loop():
        if initial_delay:
            time.sleep(initial_delay)
        if run_at_boot:
            run_script(script, label, timeout, extra_args)
        while running_check():
            effective = get_effective_interval(name, interval, override_file) if override_file else interval
            elapsed = 0
            while elapsed < effective and running_check():
                chunk = min(30, effective - elapsed)
                time.sleep(chunk)
                elapsed += chunk
                effective = get_effective_interval(name, interval, override_file) if override_file else interval
            if running_check():
                run_script(script, label, timeout, extra_args)
    t = threading.Thread(target=_loop, daemon=True, name=name)
    t.start()
