//
//  ChatView.swift
//  oAI
//
//  Main chat interface
//
// 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

struct ChatView: View {
    @Environment(ChatViewModel.self) var viewModel
    let onModelSelect: () -> Void
    let onProviderChange: (Settings.Provider) -> Void

    var body: some View {
        @Bindable var viewModel = viewModel
        VStack(spacing: 0) {
            // Header
            HeaderView(
                provider: viewModel.currentProvider,
                model: viewModel.selectedModel,
                onModelSelect: onModelSelect,
                onProviderChange: onProviderChange
            )

            // Messages
            ScrollViewReader { proxy in
                ScrollView {
                    LazyVStack(alignment: .leading, spacing: 12) {
                        ForEach(viewModel.messages) { message in
                            MessageRow(message: message, viewModel: viewModel)
                                .id(message.id)
                        }

                        // Processing indicator
                        if viewModel.isGenerating && viewModel.messages.last?.isStreaming != true {
                            ProcessingIndicator()
                                .padding(.horizontal)
                        }

                        // Invisible bottom anchor for auto-scroll
                        Color.clear
                            .frame(height: 1)
                            .id("bottom")
                    }
                    .padding()
                }
                .background(Color.oaiBackground)
                .onChange(of: viewModel.messages.count) {
                    withAnimation {
                        proxy.scrollTo("bottom", anchor: .bottom)
                    }
                }
                .onChange(of: viewModel.messages.last?.content) {
                    // Auto-scroll as streaming content arrives
                    if viewModel.isGenerating {
                        proxy.scrollTo("bottom", anchor: .bottom)
                    }
                }
            }

            // Input bar
            InputBar(
                text: $viewModel.inputText,
                isGenerating: viewModel.isGenerating,
                onlineMode: viewModel.onlineMode,
                onSend: viewModel.sendMessage,
                onCancel: viewModel.cancelGeneration,
                onToggleOnline: {
                    viewModel.onlineMode.toggle()
                    SettingsService.shared.onlineMode = viewModel.onlineMode
                }
            )

            // Footer
            FooterView(
                stats: viewModel.sessionStats,
                conversationName: viewModel.currentConversationName,
                hasUnsavedChanges: viewModel.hasUnsavedChanges,
                onQuickSave: viewModel.quickSave,
                onlineMode: viewModel.onlineMode,
                mcpEnabled: viewModel.mcpEnabled
            )
        }
        .background(Color.oaiBackground)
        .sheet(isPresented: $viewModel.showShortcuts) {
            ShortcutsView()
        }
        .sheet(isPresented: $viewModel.showSkills) {
            AgentSkillsView()
        }
        .sheet(isPresented: $viewModel.showJarvis) {
            JarvisView()
        }
        .sheet(item: Binding(
            get: { MCPService.shared.pendingBashCommand },
            set: { _ in }
        )) { pending in
            BashApprovalSheet(
                pending: pending,
                onApprove: { forSession in MCPService.shared.approvePendingBashCommand(forSession: forSession) },
                onDeny: { MCPService.shared.denyPendingBashCommand() }
            )
        }
    }
}

struct ProcessingIndicator: View {
    @State private var animating = false
    @State private var thinkingText = ThinkingVerbs.random()

    var body: some View {
        HStack(spacing: 8) {
            Text(thinkingText)
                .font(.system(size: 14, weight: .medium))
                .foregroundColor(.oaiSecondary)

            HStack(spacing: 4) {
                ForEach(0..<3) { index in
                    Circle()
                        .fill(Color.oaiSecondary)
                        .frame(width: 6, height: 6)
                        .scaleEffect(animating ? 1.0 : 0.5)
                        .animation(
                            .easeInOut(duration: 0.6)
                                .repeatForever()
                                .delay(Double(index) * 0.2),
                            value: animating
                        )
                }
            }
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 12)
        .background(Color.oaiSecondary.opacity(0.05))
        .cornerRadius(8)
        .onAppear {
            animating = true
        }
    }
}

#Preview {
    ChatView(onModelSelect: {}, onProviderChange: { _ in })
        .environment(ChatViewModel())
}
