//
//  VPNHelperProtocol.swift
//  SwanDesk — shared between the app and the privileged helper.
//
//  XPC contract between SwanDesk.app and the root daemon fi.juvex.swandeskhelper.
//  The daemon owns the strongSwan `charon` process, the VICI session, route +
//  DNS orchestration and the keepalive loop; the app drives it and renders status.
//

import Foundation

struct HelperConstants {
    /// Mach service the daemon publishes and the app connects to. Must match the
    /// `MachServices` key in SwanDeskHelperDaemon.plist and the helper's embedded
    /// Info.plist CFBundleIdentifier.
    static let machServiceName = "fi.juvex.swandeskhelper"
}

/// Functions the app may call in the privileged helper.
///
/// Access is gated by the daemon's code-signing check (`isClientTrusted`): only a
/// genuine, Apple-notarized, Juvex-signed SwanDesk.app can reach these. There is
/// no separate admin-authorization prompt — connecting/disconnecting the VPN does
/// not pop Touch ID / a password.
@objc(VPNHelperProtocol)
protocol VPNHelperProtocol {
    /// CFBundleVersion of the running daemon — used by the app to detect a stale
    /// (older) installed daemon and force a clean re-register. See `Helper`.
    func getVersion(reply: @escaping (String) -> Void)

    /// Bring the tunnel up for the given profile. `configData` is a JSON-encoded
    /// `VPNProfile` (non-secret fields); `secrets` is a JSON-encoded `VPNSecrets`
    /// (xauth password + private key PEM) passed transiently so nothing secret is
    /// persisted outside the Keychain and the helper's root-owned staging dir.
    /// Returns (status, message): 0 = connected, non-zero = failure with detail.
    func start(configData: Data, secrets: Data, reply: @escaping (Int, String) -> Void)

    /// Tear the tunnel down: terminate the IKE SA, restore DNS/search domains,
    /// remove routes, stop charon. Safe to call when already disconnected.
    func stop(reply: @escaping (Int, String) -> Void)

    /// Current runtime status as a JSON-encoded `VPNRuntimeStatus`.
    func status(reply: @escaping (Data) -> Void)

    /// Register the connecting app to receive pushed status/log callbacks. The app
    /// sets its connection's `exportedObject` to a `VPNClientProtocol` first; the
    /// helper then pushes events until that connection invalidates.
    func subscribe(reply: @escaping (Bool) -> Void)
}

/// Functions the helper calls back on the app (reverse XPC) to push live state.
@objc(VPNClientProtocol)
protocol VPNClientProtocol {
    /// A JSON-encoded `VPNRuntimeStatus` snapshot whenever the SA state changes.
    func statusChanged(_ data: Data)
    /// One line of charon/engine log for the live log pane.
    func logLine(_ line: String)
}
