//
//  oAIApp.swift
//  oAI
//
//  Main app entry point
//
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
// Copyright (C) 2026 Rune Olsen
//
// This file is part of oAI.
//
// oAI is licensed under the PolyForm Noncommercial License 1.0.0.
// You may use, study, modify, and share it for any noncommercial
// purpose. Commercial use — including selling oAI or any part of
// it, standalone or bundled into another product or service —
// requires a separate commercial license from the copyright holder.
//
// See the LICENSE file or
// <https://polyformproject.org/licenses/noncommercial/1.0.0> for
// the full license text. For commercial licensing, contact Rune
// Olsen via <https://oai.pm>.


import SwiftUI
#if os(macOS)
import AppKit
#endif

@main
struct oAIApp: App {
    @State private var chatViewModel = ChatViewModel()
    @State private var showAbout = false

    init() {
        // Start email handler on app launch
        EmailHandlerService.shared.start()

        // Start external MCP servers
        Task { @MainActor in ExternalMCPManager.shared.startAll() }

        // Sync Git changes on app launch (pull + import)
        Task {
            await GitSyncService.shared.syncOnStartup()
        }

        // Reconcile starred models with the iCloud copy (cross-machine favorites sync)
        Task {
            await BackupService.shared.syncFavoritesOnLaunch()
        }

        // Check for updates in the background
        UpdateCheckService.shared.checkForUpdates()
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(chatViewModel)
                .preferredColorScheme(.dark)
                .sheet(isPresented: $showAbout) {
                    AboutView()
                }
                #if os(macOS)
                .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
                    Task {
                        await BackupService.shared.syncFavoritesOnLaunch()
                    }
                }
                .onReceive(NotificationCenter.default.publisher(for: NSApplication.willTerminateNotification)) { _ in
                    Task { @MainActor in ExternalMCPManager.shared.stopAll() }
                    Task {
                        await chatViewModel.onAppWillTerminate()
                    }
                }
                #endif
        }
        #if os(macOS)
        .windowStyle(.hiddenTitleBar)
        .windowToolbarStyle(.unified)
        .defaultSize(width: 1024, height: 800)
        .windowResizability(.contentMinSize)
        .commands {
            // ── Apple menu ────────────────────────────────────────────────
            CommandGroup(replacing: .appInfo) {
                Button("About oAI") { showAbout = true }
            }

            CommandGroup(replacing: .appSettings) {
                Button("Settings…") { chatViewModel.showSettings = true }
                    .keyboardShortcut(",", modifiers: .command)
            }

            // ── File menu ─────────────────────────────────────────────────
            // Replacing .newItem removes the auto-added "New Window" entry
            CommandGroup(replacing: .newItem) {
                Button("New Chat") { chatViewModel.newConversation() }
                    .keyboardShortcut("n", modifiers: .command)
                Button("Clear Chat") { chatViewModel.clearChat() }
                    .keyboardShortcut("k", modifiers: .command)
                    .disabled(chatViewModel.messages.filter { $0.role != .system }.isEmpty)
            }

            CommandGroup(after: .newItem) {
                Button("Open Chat…") { chatViewModel.showConversations = true }
                    .keyboardShortcut("o", modifiers: .command)
                Button("Search Conversations") { chatViewModel.showConversations = true }
                    .keyboardShortcut("l", modifiers: .command)
            }

            CommandGroup(replacing: .saveItem) {
                Button("Save Chat") { chatViewModel.saveFromMenu() }
                    .keyboardShortcut("s", modifiers: .command)
                    .disabled(chatViewModel.messages.filter { $0.role != .system }.isEmpty)
                Button("Save Chat As…") { chatViewModel.saveAsFromMenu() }
                    .disabled(chatViewModel.messages.filter { $0.role != .system }.isEmpty)
                Button("Stats") { chatViewModel.showStats = true }
                    .keyboardShortcut("s", modifiers: [.command, .shift])
            }

            CommandGroup(after: .importExport) {
                Button("Export as Markdown…") {
                    let name = chatViewModel.currentConversationName ?? "conversation"
                    let safe = name.components(separatedBy: .whitespacesAndNewlines).joined(separator: "-")
                    chatViewModel.exportConversationWithSavePanel(format: "md", defaultFilename: "\(safe).md")
                }
                .disabled(chatViewModel.messages.filter { $0.role != .system }.isEmpty)

                Button("Export as HTML…") {
                    let name = chatViewModel.currentConversationName ?? "conversation"
                    let safe = name.components(separatedBy: .whitespacesAndNewlines).joined(separator: "-")
                    chatViewModel.exportConversationWithSavePanel(format: "html", defaultFilename: "\(safe).html")
                }
                .disabled(chatViewModel.messages.filter { $0.role != .system }.isEmpty)

                Button("Export as PDF…") {
                    let name = chatViewModel.currentConversationName ?? "conversation"
                    let safe = name.components(separatedBy: .whitespacesAndNewlines).joined(separator: "-")
                    chatViewModel.exportConversationWithSavePanel(format: "pdf", defaultFilename: "\(safe).pdf")
                }
                .disabled(chatViewModel.messages.filter { $0.role != .system }.isEmpty)
            }

            // ── Chat menu ─────────────────────────────────────────────────
            // Named "Chat" (not "View") to avoid colliding with the "View" menu
            // macOS auto-adds for NavigationSplitView (Enter Full Screen, etc.) —
            // two menus both titled "View" would otherwise appear in the menu bar.
            CommandMenu("Chat") {
                Button("Select Model") { chatViewModel.showModelSelector = true }
                    .keyboardShortcut("m", modifiers: .command)

                Button("Model Info") {
                    chatViewModel.modelInfoTarget = chatViewModel.selectedModel
                }
                .keyboardShortcut("i", modifiers: .command)
                .disabled(chatViewModel.selectedModel == nil)

                Divider()

                Button("Command History") { chatViewModel.showHistory = true }
                    .keyboardShortcut("h", modifiers: [.command, .shift])

                Button("Credits") { chatViewModel.showCredits = true }

                Divider()

                Button(chatViewModel.onlineMode ? "Online Mode: On" : "Online Mode: Off") {
                    chatViewModel.onlineMode.toggle()
                }
                .keyboardShortcut("o", modifiers: [.command, .shift])
            }

            // ── Help menu ─────────────────────────────────────────────────
            CommandGroup(replacing: .help) {
                Button("oAI Help") { openHelp() }
                    .keyboardShortcut("?", modifiers: .command)
                Divider()
                Button(UpdateCheckService.shared.isCheckingManually ? "Checking…" : "Check for Updates…") {
                    UpdateCheckService.shared.checkForUpdatesManually()
                }
                .disabled(UpdateCheckService.shared.isCheckingManually)
            }
        }
        #endif
    }

    #if os(macOS)
    private func openHelp() {
        // Opens the Help Book's index.html directly in the default browser rather than
        // through NSHelpManager/Help Viewer — see CLAUDE.md's macOS 27 beta note for why
        // (Apple's Tips.app replacement for Help Viewer can't resolve anchors on this beta).
        // Revisit once macOS 27 reaches RC.
        if let helpBookURL = Bundle.main.url(forResource: "oAI.help", withExtension: nil) {
            NSWorkspace.shared.open(helpBookURL.appendingPathComponent("Contents/Resources/en.lproj/index.html"))
        }
    }
    #endif
}
