#!/usr/bin/env bash
set -euo pipefail

if ! command -v python3 >/dev/null 2>&1; then
  echo "python3 is required to run NeuralBytes Support on Linux." >&2
  exit 1
fi

exec python3 - "$@" <<'PY'
from __future__ import annotations

import argparse
import getpass
import hashlib
import hmac
import json
import os
import platform
import shutil
import secrets
import socket
import stat
import subprocess
import sys
import time
import urllib.error
import urllib.request
from pathlib import Path

DEFAULT_RELAY_URL = "https://neuralbytes.org/vps-command-relay"
DISCONNECT_COMMAND = "__NEURALBYTES_DISCONNECT__"


def state_dir_default() -> Path:
    base = os.environ.get("XDG_STATE_HOME")
    if base:
        return Path(base) / "neuralbytes-support"
    return Path.home() / ".local" / "state" / "neuralbytes-support"


def json_post(relay_url: str, path: str, body: dict, token: str | None = None) -> dict:
    signing_path = "/" + path.strip("/")
    url = relay_url.rstrip("/") + signing_path
    data = json.dumps(body, separators=(",", ":")).encode("utf-8")
    headers = {
        "Accept": "application/json",
        "Content-Type": "application/json",
        "User-Agent": "NeuralBytesLinuxAgent/1.0",
    }
    if token:
        headers["Authorization"] = "Bearer " + token
        timestamp = str(int(time.time()))
        nonce = secrets.token_urlsafe(24)
        signing = b"\n".join(
            [
                b"POST",
                signing_path.encode("utf-8"),
                timestamp.encode("ascii"),
                nonce.encode("utf-8"),
                data,
            ]
        )
        headers["X-NB-Timestamp"] = timestamp
        headers["X-NB-Nonce"] = nonce
        headers["X-NB-Signature"] = hmac.new(token.encode("utf-8"), signing, hashlib.sha256).hexdigest()
    req = urllib.request.Request(url, data=data, method="POST", headers=headers)
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:
        payload = exc.read().decode("utf-8", errors="replace")
        try:
            detail = json.loads(payload)
        except Exception:
            detail = {"error": payload or str(exc)}
        raise RuntimeError(f"Relay HTTP {exc.code}: {detail}") from exc


def clear_state(path: Path) -> None:
    try:
        path.unlink()
    except FileNotFoundError:
        pass


def machine_meta() -> dict:
    return {
        "hostname": socket.gethostname(),
        "username": getpass.getuser(),
        "os": f"{platform.system()} {platform.release()}",
        "arch": platform.machine(),
        "agent": "NeuralBytesSupport-Linux",
        "agent_version": "1.0.0",
    }


def wait_for_approval(relay_url: str, pending_id: str, token: str, expires_at: int | None, poll_seconds: int) -> dict:
    if expires_at:
        print(f"Approval request {pending_id} sent. Expires at {time.strftime('%Y-%m-%d %H:%M:%S %Z', time.localtime(expires_at))}.")
    else:
        print(f"Approval request {pending_id} sent.")
    print("Waiting for technician approval. Press Ctrl+C to stop.")
    while True:
        status = json_post(relay_url, "/agent/approval-status", {}, token)
        current = status.get("status")
        if current == "approved":
            agent_id = status.get("agent_id")
            if not agent_id:
                raise RuntimeError("Relay approved the request but did not return a session ID.")
            return {"agent_id": agent_id, "agent_token": token, "relay_url": relay_url}
        if current == "rejected":
            raise RuntimeError("Approval request was rejected.")
        if current == "expired":
            raise RuntimeError("Approval request expired. Run the script again to request a new session.")
        time.sleep(max(2, poll_seconds))


def register_session(args: argparse.Namespace) -> dict:
    code = (args.code or "").strip().upper()
    if not code:
        raise SystemExit("A one-time support code from your NeuralBytes technician is required.")

    body = {"meta": machine_meta()}
    body["pair_code"] = code
    response = json_post(args.relay_url, "/agent/register", body)
    if response.get("status") == "pending_approval":
        return wait_for_approval(
            args.relay_url,
            response["pending_agent_id"],
            response["pending_token"],
            response.get("expires_at"),
            args.poll_seconds,
        )
    else:
        return {
            "agent_id": response["agent_id"],
            "agent_token": response["agent_token"],
            "relay_url": args.relay_url,
        }


def shell_path(shell: str | None) -> str:
    requested = (shell or "bash").lower()
    if requested == "zsh":
        return shutil.which("zsh") or "/bin/zsh"
    if requested == "sh":
        return shutil.which("sh") or "/bin/sh"
    return shutil.which("bash") or "/bin/bash"


def run_command(command: dict) -> dict:
    text = str(command.get("command") or "")
    if text == DISCONNECT_COMMAND:
        return {"exit_code": 0, "stdout": "Session closed by technician.", "stderr": ""}
    timeout = max(1, min(int(command.get("timeout_seconds") or 120), 1800))
    try:
        completed = subprocess.run(
            text,
            shell=True,
            executable=shell_path(command.get("shell")),
            capture_output=True,
            text=True,
            timeout=timeout,
            errors="replace",
        )
        return {
            "exit_code": completed.returncode,
            "stdout": completed.stdout[-220000:],
            "stderr": completed.stderr[-220000:],
        }
    except subprocess.TimeoutExpired as exc:
        return {
            "exit_code": -2,
            "stdout": (exc.stdout or "")[-220000:] if isinstance(exc.stdout, str) else "",
            "stderr": f"Command timed out after {timeout} seconds.",
        }
    except Exception as exc:
        return {"exit_code": -1, "stdout": "", "stderr": repr(exc)}


def main() -> int:
    parser = argparse.ArgumentParser(description="NeuralBytes terminal support agent for approved Linux sessions")
    parser.add_argument("--relay-url", default=DEFAULT_RELAY_URL)
    parser.add_argument("--code", required=True, help="One-time support code from the technician")
    parser.add_argument("--poll-seconds", type=int, default=3)
    parser.add_argument("--reset", action="store_true", help="Remove any old saved session state before starting")
    parser.add_argument("--state-dir", default=str(state_dir_default()), help=argparse.SUPPRESS)
    args = parser.parse_args()

    state_path = Path(args.state_dir).expanduser() / "agent-state.json"
    had_old_state = state_path.exists()
    if args.reset or had_old_state:
        clear_state(state_path)
    if args.reset:
        print("Saved NeuralBytes session state removed.")

    state = register_session(args)
    print(f"Connected to relay as session {state['agent_id']}. Press Ctrl+C to stop.")

    while True:
        try:
            next_command = json_post(args.relay_url, "/agent/next-command", {}, state["agent_token"]).get("command")
            if next_command:
                print(f"Running technician action {next_command['id'][:8]} with {next_command.get('shell') or 'bash'}...")
                result = run_command(next_command)
                json_post(
                    args.relay_url,
                    "/agent/command-result",
                    {
                        "command_id": next_command["id"],
                        "exit_code": int(result["exit_code"]),
                        "stdout": result["stdout"],
                        "stderr": result["stderr"],
                    },
                    state["agent_token"],
                )
                if next_command.get("command") == DISCONNECT_COMMAND:
                    clear_state(state_path)
                    print("Session closed by technician.")
                    return 0
                print(f"Completed action {next_command['id'][:8]} exit={result['exit_code']}.")
        except KeyboardInterrupt:
            print("\nStopped locally. The technician can no longer reach this terminal.")
            return 130
        except Exception as exc:
            print(f"Relay warning: {exc}", file=sys.stderr)
            time.sleep(max(args.poll_seconds, 10))
            continue
        time.sleep(max(2, args.poll_seconds))


if __name__ == "__main__":
    raise SystemExit(main())
PY
