import AppKit
import ApplicationServices
import CoreGraphics
import Foundation
import VMAgentCore

// NucleicVMAgent — the native in-guest automation agent (docs/MACOS_VM_NATIVE_AGENT.md).
//
// Runs as a per-user LaunchAgent in the auto-login `agent` account's Aqua session (AX, SCK and
// CGEvent all need an active WindowServer session), listens on a vsock port, and executes the §4
// wire ops with Apple's frameworks directly: AXUIElement (observe + control), ScreenCaptureKit
// (capture), CGEvent (raw input). It is a dumb, well-scoped actuator — the host keeps ownership of
// VM lifecycle, gating, and the approval boundary.

// A peer that vanishes mid-write must not kill the process — writes surface EPIPE instead.
signal(SIGPIPE, SIG_IGN)

let port = ProcessInfo.processInfo.environment["NUCLEIC_AGENT_PORT"]
    .flatMap(UInt32.init) ?? AgentWire.port

agentLog("NucleicVMAgent protocol v\(AgentWire.version) starting on vsock port \(port)")
// Self-check the TCC grants once at startup so the LaunchAgent log shows an actionable state; the
// same readiness rides in every `ping` reply so the HOST can surface "present but not authorized".
agentLog(
    "readiness: accessibility=\(AXIsProcessTrusted()) "
        + "screenRecording=\(CGPreflightScreenCaptureAccess()) "
        + "postEvent=\(CGPreflightPostEventAccess())")

let listener: AgentListener
do {
    listener = try AgentListener(port: port)
} catch {
    agentLog("FATAL: \(error) — is this running inside a macOS guest VM? (AF_VSOCK fails ENODEV on a host)")
    exit(1)
}

Thread.detachNewThread { listener.run() }
// Keep the main run loop alive: AppKit-adjacent calls (NSWorkspace, event posting) expect a main
// thread with a live dispatch queue in a GUI session.
dispatchMain()
