//
//  ContentView.swift
//  oAI
//
//  Root navigation container — NavigationSplitView with collapsible sidebar
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Rune Olsen
//
// This file is part of oAI.
//
// oAI is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// oAI is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
// Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with oAI. If not, see <https://www.gnu.org/licenses/>.


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 = .all
    @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)
        #if os(macOS)
        .onAppear {
            NSApplication.shared.windows.forEach { $0.tabbingMode = .disallowed }
            checkIntelWarning()
        }
        .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
                    let oldModel = chatViewModel.selectedModel
                    chatViewModel.selectModel(model)
                    chatViewModel.showModelSelector = false
                    Task {
                        await chatViewModel.onModelSwitch(from: oldModel, to: model)
                    }
                }
            )
            .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
            })
        }
        .alert("Intel Mac Support Ending", isPresented: $showIntelWarning) {
            Button("Got It") {
                UserDefaults.standard.set(true, forKey: "hasShownIntelWarning")
            }
        } message: {
            Text("oAI v2.4 is the last version to support Intel Macs and Rosetta. Starting with macOS 28, oAI 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)
                    }
                }
                Button("Release Page") { updateService.openReleasesPage() }
                Button("Later", role: .cancel) { }
            } else {
                Button("OK", role: .cancel) { }
            }
        } 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())
}
