//
//  SwanDeskApp.swift
//  SwanDesk — SwiftUI entry point.
//
//  A menu-bar-only app (LSUIElement). The MenuBarExtra shows a green/red/amber
//  status dot and a menu to connect/disconnect each profile and open the
//  configuration window. A Window scene hosts the configuration UI.
//

import SwiftUI
import ServiceManagement

@main
struct SwanDeskApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) private var delegate
    @State private var connection = ConnectionManager.shared
    @State private var store = ProfileStore.shared

    var body: some Scene {
        // Status-bar item. The label colour reflects the live VPN state.
        MenuBarExtra {
            MenuContentView(connection: connection, store: store)
        } label: {
            Image(systemName: connection.menuBarSymbol)
                .symbolRenderingMode(.palette)
                .foregroundStyle(connection.stateColor)
        }

        Window("SwanDesk Configuration", id: "config") {
            ConfigView(store: store, connection: connection)
                .frame(minWidth: 720, minHeight: 460)
        }
        .defaultSize(width: 820, height: 560)
        .windowResizability(.contentMinSize)
    }
}

/// Minimal app delegate: registers the daemon and subscribes to its events once
/// the app finishes launching.
final class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        // The whole app is a front-end for the privileged helper, so there is
        // nothing useful to do if we can't reach it. Bring it up (with recovery);
        // if that ultimately fails, tell the user and quit rather than sit in a
        // broken state where every connect/disconnect errors out.
        Task { @MainActor in
            if await ConnectionManager.shared.bootstrap() == false {
                Self.presentHelperFailureAndQuit()
                return
            }
            // Bring up every profile marked "connect on launch" (skipping any the
            // still-running helper kept connected across an app restart).
            await ConnectionManager.shared.autoConnectOnLaunch()
        }
    }

    @MainActor
    private static func presentHelperFailureAndQuit() {
        NSApp.activate(ignoringOtherApps: true)
        let alert = NSAlert()
        alert.alertStyle = .critical
        alert.messageText = "SwanDesk can’t reach its VPN helper"
        alert.informativeText = """
            The privileged helper couldn’t be started or contacted, so SwanDesk can’t \
            manage VPN connections and will quit.

            Open Login Items, make sure “SwanDesk” is allowed under Login Items & \
            Extensions, then launch SwanDesk again. If it keeps failing, reinstall the app.
            """
        alert.addButton(withTitle: "Quit")
        alert.addButton(withTitle: "Open Login Items")
        if alert.runModal() == .alertSecondButtonReturn {
            SMAppService.openSystemSettingsLoginItems()
        }
        NSApp.terminate(nil)
    }

    /// Disconnect any active tunnel before quitting, so we never leave the VPN up
    /// (with modified routes/DNS) and no UI to control it. Covers every quit path
    /// — the menu button, ⌘Q, and the Apple menu. Defers termination until the
    /// teardown completes.
    func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
        let connection = ConnectionManager.shared
        guard connection.hasActiveTunnel else { return .terminateNow }
        Task { @MainActor in
            await connection.disconnectForQuit()   // bounded — never hang the quit
            NSApp.reply(toApplicationShouldTerminate: true)
        }
        return .terminateLater
    }
}
