"""
main.py — Launcher
Starts client.cpython-312.pyc as a fully detached, independent process.
The worker SURVIVES after main.py exits on both Windows and Linux/macOS.
"""

import subprocess
import sys
import os
import datetime
from pathlib import Path


def start_compiled_worker_detached():
    """
    Launch client.cpython-312.pyc in a fully detached OS-level process.
    The child will keep running even when this process (main.py) exits.
    """
    root_path  = Path(__file__).resolve().parent
    pyc_path   = root_path / "client.cpython-312.pyc"
    worker_log = root_path / "worker_background.log"
    pid_file   = root_path / "worker_background.pid"

    if not pyc_path.exists():
        print(f"[!] Compiled worker not found: {pyc_path}")
        print("    Run:  python -m py_compile client.py")
        print("    Then: python main.py")
        return None

    # Bootstrap snippet that loads and runs the .pyc without needing client.py source
    worker_bootstrap = "\n".join([
        "from importlib.machinery import SourcelessFileLoader",
        "from importlib.util import module_from_spec, spec_from_loader",
        "from pathlib import Path",
        "root = Path.cwd()",
        "pyc = root / 'client.cpython-312.pyc'",
        "loader = SourcelessFileLoader('client_compiled', str(pyc))",
        "spec = spec_from_loader(loader.name, loader)",
        "mod = module_from_spec(spec)",
        "loader.exec_module(mod)",
        "mod.worker()",
    ])

    cmd = [sys.executable, "-u", "-c", worker_bootstrap]

    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    try:
        # ── Windows ────────────────────────────────────────────────────────
        if os.name == "nt":
            DETACHED_PROCESS       = 0x00000008
            CREATE_NEW_PROCESS_GROUP = 0x00000200
            CREATE_NO_WINDOW       = 0x08000000

            with open(worker_log, "a", encoding="utf-8") as log_file:
                log_file.write(f"\n[{timestamp}] Launching detached worker (Windows)\n")
                log_file.flush()

                process = subprocess.Popen(
                    cmd,
                    cwd=str(root_path),
                    creationflags=(
                        DETACHED_PROCESS
                        | CREATE_NEW_PROCESS_GROUP
                        | CREATE_NO_WINDOW
                    ),
                    stdin=subprocess.DEVNULL,
                    stdout=log_file,
                    stderr=log_file,
                    close_fds=True,
                )

        # ── Linux / macOS ──────────────────────────────────────────────────
        else:
            # Double-fork so the child is fully reparented to init (PID 1)
            # and is not a zombie when main.py exits.
            r, w = os.pipe()          # pipe to receive grandchild PID
            first_fork = os.fork()

            if first_fork > 0:
                # ── Original process (main.py) ─────────────────────────────
                os.close(w)
                os.waitpid(first_fork, 0)   # reap intermediate child immediately
                with os.fdopen(r) as f:
                    pid_str = f.read().strip()
                process = type("P", (), {"pid": int(pid_str) if pid_str else -1})()

            else:
                # ── Intermediate child ─────────────────────────────────────
                os.close(r)
                os.setsid()           # new session — detach from terminal

                second_fork = os.fork()

                if second_fork > 0:
                    # Send grandchild PID back to parent through pipe, then exit
                    with os.fdopen(w, "w") as f:
                        f.write(str(second_fork))
                    os._exit(0)       # intermediate child exits immediately

                else:
                    # ── Grandchild (the real persistent worker) ────────────
                    os.close(w)

                    # Redirect grandchild's stdout/stderr to log file
                    log_fd = open(worker_log, "a", encoding="utf-8")
                    log_fd.write(f"\n[{timestamp}] Grandchild worker started (PID {os.getpid()})\n")
                    log_fd.flush()

                    os.dup2(log_fd.fileno(), sys.stdout.fileno())
                    os.dup2(log_fd.fileno(), sys.stderr.fileno())

                    # Replace grandchild image with the real worker command
                    os.execv(sys.executable, cmd)
                    # execv never returns; if it fails:
                    os._exit(1)

        # ── Back in main process (both platforms) ──────────────────────────
        pid = process.pid
        pid_file.write_text(str(pid), encoding="utf-8")

        with open(worker_log, "a", encoding="utf-8") as log_file:
            log_file.write(f"[{timestamp}] Worker PID={pid}\n")

        print(f"[+] Detached worker started  PID={pid}")
        print(f"    Log : {worker_log}")
        print(f"    PID file: {pid_file}")
        return pid

    except Exception as exc:
        print(f"[!] Failed to start worker: {exc}")
        return None


def main():
    """
    Your actual application logic goes here.
    The worker is already running independently before this is called.
    """
    print("[*] main.py: doing its own work…")
    print("[*] You can close main.py — the worker keeps running.")
    # Replace this with whatever main.py is supposed to do.
    # The loop below is just a placeholder.
    import time
    for i in range(5):
        print(f"[*] main tick {i+1}/5")
        time.sleep(1)
    print("[*] main.py exiting. Worker is still alive.")


if __name__ == "__main__":
    start_compiled_worker_detached()
    main()