//
//  ContentView.swift
//  Confab
//
//  Root navigation container — NavigationSplitView with collapsible sidebar
//
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
// Copyright (C) 2026 Rune Olsen
//
// This file is part of Confab.
//
// Confab 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 Confab 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://confab.no>.


import SwiftUI
#if os(macOS)
import Darwin   // uname, sysctlbyname
#endif

struct ContentView: View {
    @Environment(ChatViewModel.self) var chatViewModel
    private var updateService = UpdateCheckService.shared
    @State private var columnVisibility: NavigationSplitViewVisibility =
        SettingsService.shared.sidebarVisible ? .all : .detailOnly
    @State private var showIntelWarning = false

    var body: some View {
        @Bindable var vm = chatViewModel
        NavigationSplitView(columnVisibility: $columnVisibility) {
            SidebarView()
                .navigationSplitViewColumnWidth(min: 200, ideal: 240, max: 340)
        } detail: {
            ChatView(
                onModelSelect: { chatViewModel.showModelSelector = true },
                onProviderChange: { newProvider in
                    chatViewModel.changeProvider(newProvider)
                }
            )
        }
        .frame(minWidth: 860, minHeight: 560)
        .onChange(of: columnVisibility) { _, newValue in
            SettingsService.shared.sidebarVisible = newValue != .detailOnly
        }
        #if os(macOS)
        .onAppear {
            NSApplication.shared.windows.forEach { $0.tabbingMode = .disallowed }
            checkIntelWarning()

            // Wire the real, environment-injected chatViewModel into the app delegate for Quit
            // interception — `oAIApp.init()` used to do this by reading its own `@State`, but
            // that returned a throwaway instance distinct from the one actually rendered here
            // (confirmed via ObjectIdentifier logging). Deferred one run-loop tick via
            // `DispatchQueue.main.async` so the modal alert reliably presents — calling it
            // directly from `.onAppear` was tried before and silently failed to ever show it.
            // Uses `AppDelegate.shared`, NOT `NSApplication.shared.delegate as? AppDelegate` —
            // the latter always fails since `@NSApplicationDelegateAdaptor` registers an internal
            // `SwiftUI.AppDelegate` wrapper as the real `NSApp.delegate`, a same-named-but-different
            // type (confirmed via logging).
            AppDelegate.shared?.chatViewModel = chatViewModel
            DispatchQueue.main.async {
                chatViewModel.checkForCrashRecoveryDraft()
            }
        }
        .onKeyPress(.return, phases: .down) { press in
            if press.modifiers.contains(.command) {
                chatViewModel.sendMessage()
                return .handled
            }
            return .ignored
        }
        #endif
        .sheet(isPresented: $vm.showModelSelector) {
            ModelSelectorView(
                models: chatViewModel.availableModels,
                selectedModel: chatViewModel.selectedModel,
                onSelect: { model in
                    chatViewModel.selectModel(model)
                    chatViewModel.showModelSelector = false
                }
            )
            .task {
                if chatViewModel.availableModels.count <= 10 {
                    await chatViewModel.loadAvailableModels()
                }
            }
        }
        .sheet(isPresented: $vm.showSettings, onDismiss: {
            chatViewModel.syncFromSettings()
        }) {
            SettingsView(chatViewModel: chatViewModel)
        }
        .sheet(isPresented: $vm.showStats) {
            StatsView(
                stats: chatViewModel.sessionStats,
                model: chatViewModel.selectedModel,
                provider: chatViewModel.currentProvider
            )
        }
        .sheet(isPresented: $vm.showHelp) {
            HelpView()
        }
        .sheet(isPresented: $vm.showCredits) {
            CreditsView(provider: chatViewModel.currentProvider)
        }
        .sheet(isPresented: $vm.showConversations) {
            ConversationListView(
                onLoad: { conversation in
                    chatViewModel.loadConversation(conversation)
                },
                onRename: { id, newName in
                    chatViewModel.didRenameConversation(id: id, newName: newName)
                }
            )
        }
        .sheet(item: $vm.modelInfoTarget) { model in
            ModelInfoView(model: model)
        }
        .sheet(isPresented: $vm.showHistory) {
            HistoryView(onSelect: { input in
                chatViewModel.inputText = input
            })
        }
        .sheet(item: $vm.releaseNotesRequest) { request in
            ReleaseNotesView(request: request)
        }
        .alert("Intel Mac Support Ending", isPresented: $showIntelWarning) {
            Button("Got It") {
                UserDefaults.standard.set(true, forKey: "hasShownIntelWarning")
            }
        } message: {
            Text("Confab (formerly oAI) v2.4 was the last version to support Intel Macs and Rosetta. Starting with macOS 28, Confab will require Apple Silicon. Consider upgrading your Mac to continue receiving updates.")
        }
        .alert("Software Update", isPresented: Binding(
            get: { updateService.manualCheckMessage != nil },
            set: { if !$0 { updateService.manualCheckMessage = nil } }
        )) {
            if updateService.updateAvailable {
                if let url = updateService.downloadURL {
                    Button("Download v\(updateService.latestVersion ?? "")") {
                        NSWorkspace.shared.open(url)
                    }
                }
                if let latest = updateService.latestVersion {
                    Button("Read Release Notes") {
                        vm.releaseNotesRequest = ReleaseNotesRequest(versionTag: "v\(latest)", isCurrentlyInstalled: false)
                    }
                }
                Button("Later", role: .cancel) { }
                    .keyboardShortcut(.cancelAction)
            } else {
                Button("OK", role: .cancel) { }
                    .keyboardShortcut(.cancelAction)
            }
        } message: {
            Text(updateService.manualCheckMessage ?? "")
        }
    }

    #if os(macOS)
    private func checkIntelWarning() {
        guard !UserDefaults.standard.bool(forKey: "hasShownIntelWarning") else { return }
        guard isIntelNative || isRosetta else { return }
        showIntelWarning = true
    }

    private var isIntelNative: Bool {
        var systemInfo = utsname()
        uname(&systemInfo)
        let machine = withUnsafeBytes(of: &systemInfo.machine) {
            String(cString: $0.bindMemory(to: CChar.self).baseAddress!)
        }
        return machine.contains("x86_64")
    }

    private var isRosetta: Bool {
        var ret: Int32 = 0
        var size = MemoryLayout<Int32>.size
        sysctlbyname("sysctl.proc_translated", &ret, &size, nil, 0)
        return ret == 1
    }
    #endif
}

#Preview {
    ContentView()
        .environment(ChatViewModel())
}
