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

# Add project root to path
sys.path.append(os.getcwd())

from health import config

PID_FILE = config.DATA_DIR / "bot_pids.json"
LOG_DIR = Path("logs")
LOG_DIR.mkdir(exist_ok=True)

BOTS = {
    "health": {
        "script": "slack_bot/main.py",
        "log": LOG_DIR / "health.log"
    },
    "obsidian": {
        "script": "scripts/obsidian_bot.py",
        "log": LOG_DIR / "obsidian.log"
    },
    "shell": {
        "script": "slack_bot/shell_main.py",
        "log": LOG_DIR / "shell.log"
    }
}

def load_pids():
    if not PID_FILE.exists():
        return {}
    try:
        with open(PID_FILE, "r") as f:
            return json.load(f)
    except:
        return {}

def save_pids(pids):
    with open(PID_FILE, "w") as f:
        json.dump(pids, f)

def is_running(pid):
    try:
        os.kill(pid, 0)
        return True
    except OSError:
        return False

def start_bot(name):
    pids = load_pids()
    if name in pids and is_running(pids[name]):
        print(f"✅ Bot '{name}' is already running (PID: {pids[name]})")
        return

    if name not in BOTS:
        print(f"❌ Unknown bot: {name}")
        return

    bot_cfg = BOTS[name]
    log_file = open(bot_cfg["log"], "a")
    
    # Use venv python if available
    python_exe = "venv/bin/python" if os.path.exists("venv/bin/python") else sys.executable
    
    print(f"🚀 Starting {name} bot...")
    process = subprocess.Popen(
        [python_exe, bot_cfg["script"]],
        stdout=log_file,
        stderr=log_file,
        start_new_session=True # Detach
    )
    
    pids[name] = process.pid
    save_pids(pids)
    print(f"✨ {name} started (PID: {process.pid}). Logs at {bot_cfg['log']}")

def stop_bot(name):
    pids = load_pids()
    if name not in pids or not is_running(pids[name]):
        print(f"ℹ️ Bot '{name}' is not running.")
        if name in pids: del pids[name]
        save_pids(pids)
        return

    pid = pids[name]
    print(f"🛑 Stopping {name} bot (PID: {pid})...")
    try:
        os.kill(pid, signal.SIGTERM)
        # Wait a bit
        for _ in range(5):
            if not is_running(pid):
                break
            time.sleep(1)
        
        if is_running(pid):
            print(f"⚠️ {name} did not stop gracefully, forcing...")
            os.kill(pid, signal.SIGKILL)
            
        print(f"✅ {name} stopped.")
    except Exception as e:
        print(f"❌ Error stopping {name}: {e}")
    
    del pids[name]
    save_pids(pids)

def get_start_time(pid):
    try:
        # Use simple formatting: Month Day HH:MM
        # ps -p PID -o lstart=  -> Fri Jan 23 13:03:30 2026
        out = subprocess.check_output(["ps", "-p", str(pid), "-o", "lstart="], text=True).strip()
        # Clean it up a bit if standard format
        parts = out.split()
        if len(parts) >= 4:
            # Return "Mmm DD HH:MM:SS" (Skip DayName and Year)
            return f"{parts[1]} {parts[2]} {parts[3]}"
        return out
    except:
        return "?"

def status():
    pids = load_pids()
    print(f"{'BOT':<12} | {'STATUS':<10} | {'PID':<8} | {'STARTED'}")
    print("-" * 55)
    for name in BOTS:
        pid = pids.get(name)
        running = is_running(pid) if pid else False
        stat_str = "RUNNING" if running else "STOPPED"
        pid_str = str(pid) if running else "-"
        start_str = get_start_time(pid) if running else "-"
        
        print(f"{name:<12} | {stat_str:<10} | {pid_str:<8} | {start_str}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python3 scripts/bot_manager.py [start|stop|restart|status] [bot_name|all]")
        sys.exit(1)

    cmd = sys.argv[1]
    target = sys.argv[2] if len(sys.argv) > 2 else "all"

    if cmd == "status":
        status()
    elif cmd == "start":
        if target == "all":
            for b in BOTS: start_bot(b)
        else:
            start_bot(target)
    elif cmd == "stop":
        if target == "all":
            for b in list(load_pids().keys()): stop_bot(b)
        else:
            stop_bot(target)
    elif cmd == "restart":
        if target == "all":
            for b in BOTS:
                stop_bot(b)
                start_bot(b)
        else:
            stop_bot(target)
            start_bot(target)
    else:
        print(f"Unknown command: {cmd}")
