"""Continuous Autonomous Supervisor for DSCons ERP & Cloudflare Tunnel.

Features:
- Spawns & monitors FastAPI / Uvicorn with --reload.
- Spawns & monitors Cloudflare Tunnel (cloudflared).
- Auto-restarts any failed service instantly.
- Logs lifecycle events to logs/supervisor.log.
"""

from __future__ import annotations

import subprocess
import time
from datetime import datetime
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent
LOGS_DIR = PROJECT_ROOT / "logs"
LOGS_DIR.mkdir(exist_ok=True)
SUPERVISOR_LOG = LOGS_DIR / "supervisor.log"

PYTHON_EXE = str(PROJECT_ROOT / ".venv" / "Scripts" / "python.exe")
CLOUDFLARED_EXE = r"C:\Program Files (x86)\cloudflared\cloudflared.exe"
CLOUDFLARED_CONFIG = str(Path.home() / ".cloudflared" / "config.yml")


def log(msg: str):
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    formatted = f"[{timestamp}] [SUPERVISOR] {msg}"
    print(formatted, flush=True)
    try:
        with open(SUPERVISOR_LOG, "a", encoding="utf-8") as f:
            f.write(formatted + "\n")
    except Exception:
        pass


def start_uvicorn():
    cmd = [
        PYTHON_EXE,
        "-m",
        "uvicorn",
        "app.main:app",
        "--host",
        "127.0.0.1",
        "--port",
        "8000",
        "--reload",
    ]
    log(f"Spawning Uvicorn: {' '.join(cmd)}")
    return subprocess.Popen(
        cmd,
        cwd=str(PROJECT_ROOT),
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
    )


def start_cloudflared():
    cmd = [
        CLOUDFLARED_EXE,
        "tunnel",
        "--config",
        CLOUDFLARED_CONFIG,
        "run",
        "dscons-erp",
    ]
    log(f"Spawning Cloudflared Tunnel: {' '.join(cmd)}")
    return subprocess.Popen(
        cmd,
        cwd=str(PROJECT_ROOT),
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
    )


def supervise():
    log("Starting DSCons Service Supervisor daemon...")
    uvicorn_proc = None
    cloudflared_proc = None

    try:
        while True:
            # Check Uvicorn
            if uvicorn_proc is None or uvicorn_proc.poll() is not None:
                if uvicorn_proc is not None:
                    log(
                        f"Uvicorn process exited with code {uvicorn_proc.returncode}. Restarting..."
                    )
                uvicorn_proc = start_uvicorn()

            # Check Cloudflared
            if cloudflared_proc is None or cloudflared_proc.poll() is not None:
                if cloudflared_proc is not None:
                    log(
                        f"Cloudflared process exited with code {cloudflared_proc.returncode}. Restarting..."
                    )
                cloudflared_proc = start_cloudflared()

            time.sleep(3.0)
    except KeyboardInterrupt:
        log("Supervisor interrupted by user. Stopping child processes...")
    finally:
        if uvicorn_proc and uvicorn_proc.poll() is None:
            uvicorn_proc.terminate()
        if cloudflared_proc and cloudflared_proc.poll() is None:
            cloudflared_proc.terminate()
        log("Supervisor shutdown complete.")


if __name__ == "__main__":
    supervise()
