//
//  SettingsView.swift
//  oAI
//
//  Settings and configuration screen
//
// 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
import UniformTypeIdentifiers

struct SettingsView: View {
    @Environment(\.dismiss) var dismiss
    @Bindable private var settingsService = SettingsService.shared
    private var mcpService = MCPService.shared
    private let gitSync = GitSyncService.shared
    var chatViewModel: ChatViewModel?

    init(chatViewModel: ChatViewModel? = nil) {
        self.chatViewModel = chatViewModel
    }

    @State private var openrouterKey = ""
    @State private var anthropicKey = ""
    @State private var openaiKey = ""
    @State private var googleKey = ""
    @State private var googleEngineID = ""
    @State private var selectedTab = 0
    @State private var isFolderDropTargeted = false
    @State private var logLevel: LogLevel = FileLogger.shared.minimumLevel

    // Git Sync state
    @State private var syncRepoURL = ""
    @State private var syncLocalPath = "~/oAI-sync"
    @State private var syncUsername = ""
    @State private var syncPassword = ""
    @State private var syncAccessToken = ""
    @State private var showSyncPassword = false
    @State private var showSyncToken = false
    @State private var isTestingSync = false
    @State private var syncTestResult: String?
    @State private var isSyncing = false

    // Paperless-NGX state
    @State private var paperlessURL = ""
    @State private var paperlessToken = ""
    @State private var showPaperlessToken = false
    @State private var isTestingPaperless = false
    @State private var paperlessTestResult: String?

    // Backup state
    private let backupService = BackupService.shared
    @State private var isExporting = false
    @State private var isImporting = false
    @State private var backupMessage: String?
    @State private var backupMessageIsError = false
    @State private var showRestoreFilePicker = false

    // Email handler state
    @State private var showEmailLog = false
    @State private var showEmailModelSelector = false
    @State private var emailHandlerSystemPrompt = ""
    @State private var emailAvailableModels: [ModelInfo] = []
    @State private var isLoadingEmailModels = false
    @State private var showEmailPassword = false
    @State private var isTestingEmailConnection = false
    @State private var emailConnectionTestResult: String?

    private let labelWidth: CGFloat = 160

    // Default system prompt - generic for all models
    private let defaultSystemPrompt = """
You are a helpful AI assistant. Follow these core principles:

## CORE BEHAVIOR

- **Accuracy First**: Never invent information. If unsure, say so clearly.
- **Ask for Clarification**: When ambiguous, ask questions before proceeding.
- **Be Direct**: Provide concise, relevant answers. No unnecessary preambles.
- **Show Your Work**: If you use capabilities (tools, web search, etc.), demonstrate what you did.
- **Complete Tasks Properly**: If you start something, finish it correctly.

## FORMATTING

Always use Markdown formatting:
- **Bold** for emphasis
- Code blocks with language tags: ```python
- Headings (##, ###) for structure
- Lists for organization

## HONESTY

It's better to admit "I need more information" or "I cannot do that" than to fake completion or invent answers.
"""

    var body: some View {
        VStack(spacing: 0) {
            // Header: close button (left) + active tab title (center)
            ZStack(alignment: .leading) {
                Text(tabTitle(selectedTab))
                    .font(.system(size: 15, weight: .semibold))
                    .frame(maxWidth: .infinity)
                Button(action: { dismiss() }) {
                    Image(systemName: "xmark.circle.fill")
                        .font(.system(size: 20))
                        .symbolRenderingMode(.hierarchical)
                        .foregroundStyle(.secondary)
                }
                .buttonStyle(.plain)
                .padding(.leading, 14)
            }
            .padding(.top, 14)
            .padding(.bottom, 4)

            // Icon toolbar — Core | separator | Extras
            HStack(spacing: 0) {
                tabButton(0, icon: "gear",                        label: "General")
                tabButton(1, icon: "folder.badge.gearshape",     label: "MCP")
                tabButton(2, icon: "paintbrush",                  label: "Appearance")
                tabButton(3, icon: "slider.horizontal.3",         label: "Advanced")

                Divider().frame(height: 44).padding(.horizontal, 8)

                tabButton(6, icon: "command",                     label: "Shortcuts")
                tabButton(7, icon: "brain",                       label: "Skills")
                tabButton(4, icon: "arrow.triangle.2.circlepath", label: "Sync")
                tabButton(5, icon: "envelope",                    label: "Email")
                tabButton(8, icon: "doc.text",                    label: "Paperless", beta: true)
                tabButton(9, icon: "icloud.and.arrow.up",         label: "Backup")
            }
            .padding(.horizontal, 16)
            .padding(.bottom, 12)

            Divider()

            ScrollView {
                VStack(alignment: .leading, spacing: 20) {
                    switch selectedTab {
                    case 0:
                        generalTab
                    case 1:
                        mcpTab
                    case 2:
                        appearanceTab
                    case 3:
                        advancedTab
                    case 4:
                        syncTab
                    case 5:
                        emailTab
                    case 6:
                        shortcutsTab
                    case 7:
                        agentSkillsTab
                    case 8:
                        paperlessTab
                    case 9:
                        backupTab
                    default:
                        generalTab
                    }
                }
                .padding(.horizontal, 24)
                .padding(.vertical, 16)
            }

        }
        .frame(minWidth: 860, idealWidth: 940, minHeight: 620, idealHeight: 760)
        .sheet(isPresented: $showEmailLog) {
            EmailLogView()
        }
        .fileImporter(
            isPresented: $showRestoreFilePicker,
            allowedContentTypes: [.json],
            allowsMultipleSelection: false
        ) { result in
            switch result {
            case .success(let urls):
                guard let url = urls.first else { return }
                Task { await performRestore(from: url) }
            case .failure(let error):
                backupMessage = "Could not open file: \(error.localizedDescription)"
                backupMessageIsError = true
            }
        }
    }

    // MARK: - General Tab

    @ViewBuilder
    private var generalTab: some View {
        // Provider
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Provider")
            formSection {
                row("Default Provider") {
                    Picker("", selection: $settingsService.defaultProvider) {
                        ForEach(ProviderRegistry.shared.configuredProviders, id: \.self) { provider in
                            Text(provider.displayName).tag(provider)
                        }
                    }
                    .labelsHidden()
                    .fixedSize()
                }
            }
        }

        // API Keys
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("API Keys")
            formSection {
                row("OpenRouter") {
                    SecureField("sk-or-...", text: $openrouterKey)
                        .textFieldStyle(.roundedBorder)
                        .font(.system(size: 13))
                        .frame(width: 360)
                        .onAppear { openrouterKey = settingsService.openrouterAPIKey ?? "" }
                        .onChange(of: openrouterKey) {
                            settingsService.openrouterAPIKey = openrouterKey.isEmpty ? nil : openrouterKey
                            ProviderRegistry.shared.clearCache()
                        }
                }
                rowDivider()
                row("Anthropic") {
                    SecureField("sk-ant-... (API key)", text: $anthropicKey)
                        .textFieldStyle(.roundedBorder)
                        .frame(width: 360)
                        .onAppear { anthropicKey = settingsService.anthropicAPIKey ?? "" }
                        .onChange(of: anthropicKey) {
                            settingsService.anthropicAPIKey = anthropicKey.isEmpty ? nil : anthropicKey
                            ProviderRegistry.shared.clearCache()
                        }
                }
                rowDivider()
                row("OpenAI") {
                    SecureField("sk-...", text: $openaiKey)
                        .textFieldStyle(.roundedBorder)
                        .frame(width: 360)
                        .onAppear { openaiKey = settingsService.openaiAPIKey ?? "" }
                        .onChange(of: openaiKey) {
                            settingsService.openaiAPIKey = openaiKey.isEmpty ? nil : openaiKey
                            ProviderRegistry.shared.clearCache()
                        }
                }
                rowDivider()
                row("Ollama URL") {
                    TextField("http://localhost:11434", text: $settingsService.ollamaBaseURL)
                        .textFieldStyle(.roundedBorder)
                        .frame(width: 360)
                        .help("Enter your Ollama server URL to enable the Ollama provider")
                }
            }
        }

        // Features
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Features")
            formSection {
                row("Online Mode (Web Search)") {
                    Toggle("", isOn: $settingsService.onlineMode)
                        .toggleStyle(.switch)
                }
                rowDivider()
                row("Conversation Memory") {
                    Toggle("", isOn: $settingsService.memoryEnabled)
                        .toggleStyle(.switch)
                }
                rowDivider()
                row("Reasoning (Thinking)") {
                    Toggle("", isOn: $settingsService.reasoningEnabled)
                        .toggleStyle(.switch)
                }
                if settingsService.reasoningEnabled {
                    rowDivider()
                    row("Reasoning Effort") {
                        Picker("", selection: $settingsService.reasoningEffort) {
                            Text("High (~80%)").tag("high")
                            Text("Medium (~50%)").tag("medium")
                            Text("Low (~20%)").tag("low")
                            Text("Minimal (~10%)").tag("minimal")
                        }
                        .labelsHidden()
                        .fixedSize()
                    }
                    VStack(alignment: .leading, spacing: 2) {
                        Text(reasoningEffortDescription)
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                    .padding(.horizontal, 12)
                    .padding(.bottom, 4)
                    rowDivider()
                    row("Hide Reasoning in Response") {
                        Toggle("", isOn: $settingsService.reasoningExclude)
                            .toggleStyle(.switch)
                    }
                    VStack(alignment: .leading, spacing: 2) {
                        Text("Model thinks internally but reasoning is not shown in chat")
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                    .padding(.horizontal, 12)
                    .padding(.bottom, 4)
                }
            }
        }

        // Web Search
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Web Search")
            formSection {
                row("Search Provider") {
                    Picker("", selection: $settingsService.searchProvider) {
                        ForEach(Settings.SearchProvider.allCases, id: \.self) { provider in
                            Text(provider.displayName).tag(provider)
                        }
                    }
                    .labelsHidden()
                    .fixedSize()
                }
                if settingsService.searchProvider == .google {
                    rowDivider()
                    row("Google API Key") {
                        SecureField("", text: $googleKey)
                            .textFieldStyle(.roundedBorder)
                            .frame(width: 300)
                            .onAppear { googleKey = settingsService.googleAPIKey ?? "" }
                            .onChange(of: googleKey) {
                                settingsService.googleAPIKey = googleKey.isEmpty ? nil : googleKey
                            }
                    }
                    rowDivider()
                    row("Search Engine ID") {
                        TextField("", text: $googleEngineID)
                            .textFieldStyle(.roundedBorder)
                            .frame(width: 300)
                            .onAppear { googleEngineID = settingsService.googleSearchEngineID ?? "" }
                            .onChange(of: googleEngineID) {
                                settingsService.googleSearchEngineID = googleEngineID.isEmpty ? nil : googleEngineID
                            }
                    }
                }
            }
        }

        // Model Settings
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Model Settings")
            formSection {
                row("Default Model ID") {
                    TextField("e.g. anthropic/claude-sonnet-4", text: Binding(
                        get: { settingsService.defaultModel ?? "" },
                        set: { settingsService.defaultModel = $0.isEmpty ? nil : $0 }
                    ))
                    .textFieldStyle(.roundedBorder)
                    .frame(width: 300)
                }
            }
        }

        // Logging
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Logging")
            formSection {
                row("Log Level") {
                    Picker("", selection: Binding(
                        get: { logLevel },
                        set: { logLevel = $0; FileLogger.shared.minimumLevel = $0 }
                    )) {
                        ForEach(LogLevel.allCases, id: \.self) { level in
                            Text(level.displayName).tag(level)
                        }
                    }
                    .labelsHidden()
                    .fixedSize()
                }
            }
        }
        Text("Controls which messages are written to ~/Library/Logs/oAI.log")
            .font(.system(size: 13))
            .foregroundStyle(.secondary)
            .fixedSize(horizontal: false, vertical: true)
            .padding(.horizontal, 4)
    }

    // MARK: - MCP Tab

    @ViewBuilder
    private var mcpTab: some View {
        // Description header
        VStack(alignment: .leading, spacing: 8) {
            HStack(spacing: 8) {
                Image(systemName: "folder.badge.gearshape")
                    .font(.title2)
                    .foregroundStyle(.blue)
                Text("Model Context Protocol")
                    .font(.system(size: 18, weight: .semibold))
            }
            Text("MCP gives the AI controlled access to read and optionally write files on your computer. The AI can search, read, and analyze files in allowed folders to help with coding, analysis, and other tasks.")
                .font(.system(size: 14))
                .foregroundStyle(.secondary)
                .fixedSize(horizontal: false, vertical: true)
        }
        .padding(.bottom, 8)

        // Status
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Status")
            formSection {
                row("Enable MCP") {
                    Toggle("", isOn: $settingsService.mcpEnabled)
                        .toggleStyle(.switch)
                }
            }
        }
        HStack(spacing: 4) {
            Image(systemName: settingsService.mcpEnabled ? "checkmark.circle.fill" : "circle")
                .foregroundStyle(settingsService.mcpEnabled ? .green : .secondary)
                .font(.system(size: 13))
            Text(settingsService.mcpEnabled ? "Active - AI can access allowed folders" : "Disabled - No file access")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
        }
        .padding(.horizontal, 4)

        if settingsService.mcpEnabled {
            // Folders
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Allowed Folders")
                // Folder list — also a drop target for Finder drags
                VStack(spacing: 0) {
                    if mcpService.allowedFolders.isEmpty {
                        VStack(spacing: 8) {
                            Image(systemName: "folder.badge.plus")
                                .font(.system(size: 32))
                                .foregroundStyle(isFolderDropTargeted ? AnyShapeStyle(Color.accentColor) : AnyShapeStyle(.tertiary))
                            Text(isFolderDropTargeted ? "Drop to add folder" : "No folders added yet")
                                .font(.system(size: 14, weight: .medium))
                                .foregroundStyle(isFolderDropTargeted ? AnyShapeStyle(Color.accentColor) : AnyShapeStyle(.secondary))
                            if !isFolderDropTargeted {
                                Text("Click 'Add Folder' below or drag folders here from Finder")
                                    .font(.system(size: 13))
                                    .foregroundStyle(.tertiary)
                            }
                        }
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 24)
                    } else {
                        ForEach(Array(mcpService.allowedFolders.enumerated()), id: \.offset) { index, folder in
                            HStack(spacing: 8) {
                                Image(systemName: "folder.fill")
                                    .foregroundStyle(.blue)
                                    .frame(width: 20)
                                VStack(alignment: .leading, spacing: 0) {
                                    Text((folder as NSString).lastPathComponent)
                                        .font(.body)
                                    Text(abbreviatePath(folder))
                                        .font(.system(size: 13))
                                        .foregroundStyle(.secondary)
                                }
                                Spacer()
                                Button {
                                    withAnimation { _ = mcpService.removeFolder(at: index) }
                                } label: {
                                    Image(systemName: "trash.fill")
                                        .foregroundStyle(.red)
                                        .font(.system(size: 13))
                                }
                                .buttonStyle(.plain)
                            }
                            .padding(.horizontal, 16)
                            .padding(.vertical, 10)
                            if index < mcpService.allowedFolders.count - 1 {
                                rowDivider()
                            }
                        }
                    }
                }
                .background(.regularMaterial)
                .clipShape(RoundedRectangle(cornerRadius: 10))
                .overlay(
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(
                            isFolderDropTargeted ? Color.accentColor : Color.primary.opacity(0.10),
                            lineWidth: isFolderDropTargeted ? 2 : 0.5
                        )
                )
                .onDrop(of: [.fileURL], isTargeted: $isFolderDropTargeted) { providers in
                    for provider in providers {
                        _ = provider.loadObject(ofClass: URL.self) { url, _ in
                            guard let url, url.hasDirectoryPath else { return }
                            DispatchQueue.main.async {
                                withAnimation { _ = mcpService.addFolder(url.path) }
                            }
                        }
                    }
                    return true
                }

                // Add Folder button
                Button {
                    let panel = NSOpenPanel()
                    panel.canChooseFiles = false
                    panel.canChooseDirectories = true
                    panel.allowsMultipleSelection = true
                    panel.prompt = "Add"
                    panel.message = "Choose folders to allow AI access"
                    panel.begin { response in
                        guard response == .OK else { return }
                        for url in panel.urls {
                            withAnimation { _ = mcpService.addFolder(url.path) }
                        }
                    }
                } label: {
                    Label("Add Folder…", systemImage: "plus")
                        .font(.system(size: 13, weight: .medium))
                        .foregroundStyle(.white)
                        .padding(.horizontal, 14)
                        .padding(.vertical, 7)
                        .background(Color.accentColor)
                        .clipShape(RoundedRectangle(cornerRadius: 8))
                }
                .buttonStyle(.plain)
            }

            // Permissions
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Permissions")
                formSection {
                    VStack(alignment: .leading, spacing: 4) {
                        HStack(spacing: 6) {
                            Image(systemName: "checkmark.circle.fill")
                                .foregroundStyle(.green)
                                .font(.system(size: 12))
                            Text("Read access (always enabled)")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                        Text("The AI can read and search files in allowed folders")
                            .font(.system(size: 12))
                            .foregroundStyle(.tertiary)
                            .padding(.leading, 18)
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 10)
                    rowDivider()
                    row("Write & Edit Files") {
                        Toggle("", isOn: $settingsService.mcpCanWriteFiles)
                            .toggleStyle(.switch)
                    }
                    rowDivider()
                    row("Delete Files") {
                        Toggle("", isOn: $settingsService.mcpCanDeleteFiles)
                            .toggleStyle(.switch)
                    }
                    rowDivider()
                    row("Create Directories") {
                        Toggle("", isOn: $settingsService.mcpCanCreateDirectories)
                            .toggleStyle(.switch)
                    }
                    rowDivider()
                    row("Move & Copy Files") {
                        Toggle("", isOn: $settingsService.mcpCanMoveFiles)
                            .toggleStyle(.switch)
                    }
                }
            }

            // Filtering
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Filtering")
                formSection {
                    row("Respect .gitignore") {
                        Toggle("", isOn: Binding(
                            get: { settingsService.mcpRespectGitignore },
                            set: { newValue in
                                settingsService.mcpRespectGitignore = newValue
                                mcpService.reloadGitignores()
                            }
                        ))
                        .toggleStyle(.switch)
                    }
                }
            }
            Text("When enabled, listing and searching skip gitignored files. Write operations always ignore .gitignore.")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
                .fixedSize(horizontal: false, vertical: true)
                .padding(.horizontal, 4)
        }

        // Anytype integration UI hidden (work in progress — see AnytypeMCPService.swift)

        // MARK: Bash Execution
        Divider()

        VStack(alignment: .leading, spacing: 8) {
            HStack(spacing: 8) {
                Image(systemName: "terminal.fill")
                    .font(.title2)
                    .foregroundStyle(.orange)
                Text("Bash Execution")
                    .font(.system(size: 18, weight: .semibold))
            }
            Text("Allow the AI to run shell commands on your machine. Commands are executed via /bin/zsh. Enable approval mode to review each command before it runs.")
                .font(.system(size: 14))
                .foregroundStyle(.secondary)
                .fixedSize(horizontal: false, vertical: true)
        }
        .padding(.bottom, 4)

        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Status")
            formSection {
                row("Enable Bash Execution") {
                    Toggle("", isOn: $settingsService.bashEnabled)
                        .toggleStyle(.switch)
                }
            }
        }

        HStack(spacing: 4) {
            Image(systemName: settingsService.bashEnabled ? "checkmark.circle.fill" : "circle")
                .foregroundStyle(settingsService.bashEnabled ? .orange : .secondary)
                .font(.system(size: 13))
            Text(settingsService.bashEnabled ? "Active — AI can run shell commands" : "Disabled")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
        }
        .padding(.horizontal, 4)

        if settingsService.bashEnabled {
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Settings")
                formSection {
                    row("Require Approval") {
                        Toggle("", isOn: $settingsService.bashRequireApproval)
                            .toggleStyle(.switch)
                    }
                    rowDivider()
                    row("Working Directory") {
                        TextField("~", text: $settingsService.bashWorkingDirectory)
                            .textFieldStyle(.plain)
                            .font(.system(size: 13, design: .monospaced))
                            .multilineTextAlignment(.trailing)
                            .frame(width: 200)
                    }
                    rowDivider()
                    row("Timeout (seconds)") {
                        HStack(spacing: 8) {
                            Stepper("", value: $settingsService.bashTimeout, in: 5...300, step: 5)
                                .labelsHidden()
                            Text("\(settingsService.bashTimeout)s")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                                .frame(width: 36, alignment: .trailing)
                        }
                    }
                }
            }

            if settingsService.bashRequireApproval {
                HStack(spacing: 6) {
                    Image(systemName: "hand.raised.fill")
                        .font(.system(size: 12))
                        .foregroundStyle(.orange)
                    Text("Each command will require your approval before running.")
                        .font(.system(size: 13))
                        .foregroundStyle(.secondary)
                }
                .padding(.horizontal, 4)
            } else {
                HStack(alignment: .top, spacing: 6) {
                    Image(systemName: "exclamationmark.triangle.fill")
                        .font(.system(size: 12))
                        .foregroundStyle(.red)
                        .padding(.top, 1)
                    Text("Auto-execute mode: commands run without approval. Use with caution.")
                        .font(.system(size: 13))
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
                .padding(.horizontal, 4)
            }
        }
    }

    // MARK: - Appearance Tab

    @ViewBuilder
    private var appearanceTab: some View {
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Text Sizes")
            formSection {
                row("GUI Text") {
                    HStack(spacing: 8) {
                        Slider(value: $settingsService.guiTextSize, in: 10...20, step: 1)
                            .frame(maxWidth: 200)
                        Text("\(Int(settingsService.guiTextSize)) pt")
                            .font(.system(size: 13))
                            .foregroundStyle(.secondary)
                            .frame(width: 40)
                    }
                }
                rowDivider()
                row("Dialog Text") {
                    HStack(spacing: 8) {
                        Slider(value: $settingsService.dialogTextSize, in: 10...24, step: 1)
                            .frame(maxWidth: 200)
                        Text("\(Int(settingsService.dialogTextSize)) pt")
                            .font(.system(size: 13))
                            .foregroundStyle(.secondary)
                            .frame(width: 40)
                    }
                }
                rowDivider()
                row("Input Text") {
                    HStack(spacing: 8) {
                        Slider(value: $settingsService.inputTextSize, in: 10...24, step: 1)
                            .frame(maxWidth: 200)
                        Text("\(Int(settingsService.inputTextSize)) pt")
                            .font(.system(size: 13))
                            .foregroundStyle(.secondary)
                            .frame(width: 40)
                    }
                }
            }
        }

        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Toolbar")
            formSection {
                row("Icon Size") {
                    HStack(spacing: 8) {
                        Slider(value: $settingsService.toolbarIconSize, in: 16...32, step: 2)
                            .frame(maxWidth: 200)
                        Text("\(Int(settingsService.toolbarIconSize)) pt")
                            .font(.system(size: 13))
                            .foregroundStyle(.secondary)
                            .frame(width: 40)
                    }
                }
                rowDivider()
                row("Show Icon Labels") {
                    Toggle("", isOn: $settingsService.showToolbarLabels)
                        .toggleStyle(.switch)
                }
            }
        }
        Text("Show text labels below toolbar icons (helpful for new users)")
            .font(.system(size: 11))
            .foregroundStyle(.secondary)
            .padding(.horizontal, 4)
    }

    // MARK: - Advanced Tab

    @ViewBuilder
    private var advancedTab: some View {
        // Response Generation
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Response Generation")
            formSection {
                row("Enable Streaming") {
                    Toggle("", isOn: $settingsService.streamEnabled)
                        .toggleStyle(.switch)
                }
            }
        }
        Text("Stream responses as they're generated. Disable for single, complete responses.")
            .font(.system(size: 13))
            .foregroundStyle(.secondary)
            .fixedSize(horizontal: false, vertical: true)
            .padding(.horizontal, 4)

        // Model Parameters
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Model Parameters")
            formSection {
                row("Max Tokens") {
                    HStack(spacing: 8) {
                        Slider(value: Binding(
                            get: { Double(settingsService.maxTokens) },
                            set: { settingsService.maxTokens = Int($0) }
                        ), in: 0...32000, step: 256)
                            .frame(maxWidth: 250)
                        Text(settingsService.maxTokens == 0 ? "Default" : "\(settingsService.maxTokens)")
                            .font(.system(size: 13))
                            .foregroundStyle(.secondary)
                            .frame(width: 70, alignment: .leading)
                    }
                }
                rowDivider()
                row("Temperature") {
                    HStack(spacing: 8) {
                        Slider(value: $settingsService.temperature, in: 0...2, step: 0.1)
                            .frame(maxWidth: 250)
                        Text(settingsService.temperature == 0.0 ? "Default" : String(format: "%.1f", settingsService.temperature))
                            .font(.system(size: 13))
                            .foregroundStyle(.secondary)
                            .frame(width: 70, alignment: .leading)
                    }
                }
            }
        }
        VStack(alignment: .leading, spacing: 2) {
            Text("Max Tokens: set to 0 to use model default. Higher values allow longer responses.")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
            Text("Temperature: 0 = model default · 0.0–0.7 = focused · 0.8–2.0 = creative")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
        }
        .fixedSize(horizontal: false, vertical: true)
        .padding(.horizontal, 4)

        // System Prompts
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("System Prompts")
            formSection {
                // Default prompt (read-only)
                VStack(alignment: .leading, spacing: 6) {
                    HStack(spacing: 4) {
                        Text("Default Prompt")
                            .font(.system(size: 14))
                            .fontWeight(.medium)
                        Text("(always used)")
                            .font(.system(size: 13))
                            .foregroundStyle(.secondary)
                    }
                    ScrollView {
                        Text(defaultSystemPrompt)
                            .font(.system(size: 13, design: .monospaced))
                            .foregroundStyle(.secondary)
                            .textSelection(.enabled)
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .padding(8)
                    }
                    .frame(height: 140)
                    .background(Color(NSColor.textBackgroundColor))
                    .cornerRadius(6)
                    .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color.secondary.opacity(0.2), lineWidth: 1))
                    Text("This default prompt is always included to ensure accurate, helpful responses.")
                        .font(.system(size: 13))
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 12)

                rowDivider()

                // Custom prompt mode toggle
                row("Use Only Your Prompt") {
                    HStack(spacing: 8) {
                        Toggle("", isOn: Binding(
                            get: { settingsService.customPromptMode == .replace },
                            set: { settingsService.customPromptMode = $0 ? .replace : .append }
                        ))
                        .toggleStyle(.switch)
                        .labelsHidden()
                        Text(settingsService.customPromptMode == .replace ? "BYOP Mode" : "Default + Custom")
                            .font(.system(size: 13))
                            .foregroundStyle(settingsService.customPromptMode == .replace ? .orange : .secondary)
                    }
                }

                rowDivider()

                // Custom prompt (editable)
                VStack(alignment: .leading, spacing: 6) {
                    HStack(spacing: 4) {
                        Text(settingsService.customPromptMode == .replace
                             ? "Now using only your prompt shown below"
                             : "Your Custom Prompt")
                            .font(.system(size: 14))
                            .fontWeight(.medium)
                            .foregroundStyle(settingsService.customPromptMode == .replace ? .orange : .primary)
                        if settingsService.customPromptMode == .append {
                            Text("(optional)")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                    }
                    TextEditor(text: Binding(
                        get: { settingsService.systemPrompt ?? "" },
                        set: { settingsService.systemPrompt = $0.isEmpty ? nil : $0 }
                    ))
                    .font(.system(size: 13, design: .monospaced))
                    .frame(height: 100)
                    .padding(8)
                    .background(Color(NSColor.textBackgroundColor))
                    .cornerRadius(6)
                    .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color.secondary.opacity(0.3), lineWidth: 1))
                    Text(settingsService.customPromptMode == .append
                         ? "This will be added after the default prompt and tool-specific guidelines."
                         : "⚠️ In BYOP mode, ONLY your custom prompt will be used. Default prompt and tool guidelines are disabled.")
                        .font(.system(size: 13))
                        .foregroundStyle(settingsService.customPromptMode == .replace ? .orange : .secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 12)
            }
        }

        // Memory & Context
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Memory & Context")
            formSection {
                row("Smart Context Selection") {
                    Toggle("", isOn: $settingsService.contextSelectionEnabled)
                        .toggleStyle(.switch)
                }
                if settingsService.contextSelectionEnabled {
                    rowDivider()
                    row("Max Context Tokens") {
                        HStack(spacing: 8) {
                            TextField("", value: $settingsService.contextMaxTokens, format: .number)
                                .textFieldStyle(.roundedBorder)
                                .frame(width: 120)
                            Text("tokens")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                    }
                }
            }
        }
        Text("Automatically select relevant messages instead of sending all history. Reduces token usage for long conversations.")
            .font(.system(size: 13))
            .foregroundStyle(.secondary)
            .fixedSize(horizontal: false, vertical: true)
            .padding(.horizontal, 4)

        // Semantic Search
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Semantic Search")
            formSection {
                row("Enable Embeddings") {
                    Toggle("", isOn: $settingsService.embeddingsEnabled)
                        .toggleStyle(.switch)
                        .disabled(!EmbeddingService.shared.isAvailable)
                }
                if settingsService.embeddingsEnabled {
                    rowDivider()
                    row("Model") {
                        Picker("", selection: $settingsService.embeddingProvider) {
                            if settingsService.openaiAPIKey != nil && !settingsService.openaiAPIKey!.isEmpty {
                                Text("OpenAI (text-embedding-3-small)").tag("openai-small")
                                Text("OpenAI (text-embedding-3-large)").tag("openai-large")
                            }
                            if settingsService.openrouterAPIKey != nil && !settingsService.openrouterAPIKey!.isEmpty {
                                Text("OpenRouter (OpenAI small)").tag("openrouter-openai-small")
                                Text("OpenRouter (OpenAI large)").tag("openrouter-openai-large")
                                Text("OpenRouter (Qwen 8B)").tag("openrouter-qwen")
                            }
                            if settingsService.googleAPIKey != nil && !settingsService.googleAPIKey!.isEmpty {
                                Text("Google (Gemini embedding)").tag("google-gemini")
                            }
                        }
                        .pickerStyle(.menu)
                    }
                }
            }
        }
        if let provider = EmbeddingService.shared.getBestAvailableProvider() {
            Text("Enable AI-powered semantic search using \(provider.displayName) embeddings. Cost: ~$0.02–0.15/1M tokens.")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
                .fixedSize(horizontal: false, vertical: true)
                .padding(.horizontal, 4)
        } else {
            Text("⚠️ No embedding providers available. Configure an API key for OpenAI, OpenRouter, or Google in the General tab.")
                .font(.system(size: 13))
                .foregroundStyle(.orange)
                .fixedSize(horizontal: false, vertical: true)
                .padding(.horizontal, 4)
        }
        if settingsService.embeddingsEnabled {
            HStack {
                Button("Embed All Conversations") {
                    Task {
                        if let chatVM = chatViewModel {
                            await chatVM.batchEmbedAllConversations()
                        }
                    }
                }
                .help("Generate embeddings for all existing messages (one-time operation)")
                Spacer()
            }
            .padding(.horizontal, 4)
            Text("⚠️ One-time operation — generates embeddings for all messages. Estimated cost: ~$0.04 for 10,000 messages.")
                .font(.system(size: 13))
                .foregroundStyle(.orange)
                .fixedSize(horizontal: false, vertical: true)
                .padding(.horizontal, 4)
        }

        // Progressive Summarization
        VStack(alignment: .leading, spacing: 6) {
            sectionHeader("Progressive Summarization")
            formSection {
                row("Enable Summarization") {
                    Toggle("", isOn: $settingsService.progressiveSummarizationEnabled)
                        .toggleStyle(.switch)
                }
                if settingsService.progressiveSummarizationEnabled {
                    rowDivider()
                    row("Message Threshold") {
                        HStack(spacing: 8) {
                            TextField("", value: $settingsService.summarizationThreshold, format: .number)
                                .textFieldStyle(.roundedBorder)
                                .frame(width: 80)
                            Text("messages")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                    }
                }
            }
        }
        Text("Automatically summarize old portions of long conversations to save tokens and improve context efficiency.")
            .font(.system(size: 13))
            .foregroundStyle(.secondary)
            .fixedSize(horizontal: false, vertical: true)
            .padding(.horizontal, 4)

        // Info
        VStack(alignment: .leading, spacing: 8) {
            Text("⚠️ These are advanced settings")
                .font(.system(size: 13, weight: .medium))
                .foregroundStyle(.orange)
            Text("Changing these values affects how the AI generates responses. The defaults work well for most use cases.")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
                .fixedSize(horizontal: false, vertical: true)
        }
        .padding(12)
        .background(Color.orange.opacity(0.05))
        .clipShape(RoundedRectangle(cornerRadius: 10))
        .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.orange.opacity(0.15), lineWidth: 0.5))
    }

    // MARK: - Sync Tab

    @ViewBuilder
    private var syncTab: some View {
        Group {
            // Enable toggle
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Git Sync")
                formSection {
                    row("Enable Git Sync") {
                        Toggle("", isOn: $settingsService.syncEnabled)
                            .toggleStyle(.switch)
                    }
                }
            }
            Text("Sync conversations and settings across multiple machines using Git.")
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
                .fixedSize(horizontal: false, vertical: true)
                .padding(.horizontal, 4)

            if settingsService.syncEnabled {
                // Status indicator
                HStack(spacing: 8) {
                    Image(systemName: syncStatusIcon)
                        .foregroundStyle(syncStatusColor)
                    Text(syncStatusText)
                        .font(.system(size: 14))
                        .foregroundStyle(syncStatusColor)
                }
                .padding(.horizontal, 4)

                // Connection
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Connection")
                    formSection {
                        row("URL") {
                            TextField("https://github.com/user/oai-sync.git", text: $syncRepoURL)
                                .textFieldStyle(.roundedBorder)
                                .onChange(of: syncRepoURL) {
                                    settingsService.syncRepoURL = syncRepoURL
                                }
                        }
                        rowDivider()
                        row("Local Path") {
                            TextField("~/Library/Application Support/oAI/sync", text: $syncLocalPath)
                                .textFieldStyle(.roundedBorder)
                                .onChange(of: syncLocalPath) {
                                    settingsService.syncLocalPath = syncLocalPath
                                }
                        }
                    }
                }
                Text("💡 Use HTTPS URL (e.g., https://gitlab.pm/user/repo.git) — works with all auth methods.")
                    .font(.system(size: 13))
                    .foregroundStyle(.secondary)
                    .padding(.horizontal, 4)

                // Authentication
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Authentication")
                    formSection {
                        row("Method") {
                            Picker("", selection: $settingsService.syncAuthMethod) {
                                Text("SSH Key").tag("ssh")
                                Text("Username + Password").tag("password")
                                Text("Access Token").tag("token")
                            }
                            .pickerStyle(.segmented)
                            .frame(width: 360)
                        }

                        if settingsService.syncAuthMethod == "ssh" {
                            VStack(alignment: .leading, spacing: 4) {
                                Text("ℹ️ SSH Key Authentication")
                                    .font(.system(size: 13, weight: .semibold))
                                Text("• Uses your system SSH keys (~/.ssh/id_ed25519)")
                                    .font(.system(size: 13))
                                Text("• Add public key to your git provider")
                                    .font(.system(size: 13))
                                Text("• No credentials needed in oAI")
                                    .font(.system(size: 13))
                            }
                            .foregroundStyle(.secondary)
                            .padding(.horizontal, 16)
                            .padding(.bottom, 12)
                        }

                        if settingsService.syncAuthMethod == "password" {
                            rowDivider()
                            row("Username") {
                                TextField("username", text: $syncUsername)
                                    .textFieldStyle(.roundedBorder)
                                    .onChange(of: syncUsername) {
                                        settingsService.syncUsername = syncUsername.isEmpty ? nil : syncUsername
                                    }
                            }
                            rowDivider()
                            row("Password") {
                                HStack {
                                    if showSyncPassword {
                                        TextField("", text: $syncPassword)
                                            .textFieldStyle(.roundedBorder)
                                    } else {
                                        SecureField("", text: $syncPassword)
                                            .textFieldStyle(.roundedBorder)
                                    }
                                    Button(action: { showSyncPassword.toggle() }) {
                                        Image(systemName: showSyncPassword ? "eye.slash" : "eye")
                                            .foregroundStyle(.secondary)
                                    }
                                    .buttonStyle(.plain)
                                    .onChange(of: syncPassword) {
                                        settingsService.syncPassword = syncPassword.isEmpty ? nil : syncPassword
                                    }
                                }
                            }
                        }

                        if settingsService.syncAuthMethod == "token" {
                            rowDivider()
                            row("Token") {
                                HStack {
                                    if showSyncToken {
                                        TextField("", text: $syncAccessToken)
                                            .textFieldStyle(.roundedBorder)
                                    } else {
                                        SecureField("", text: $syncAccessToken)
                                            .textFieldStyle(.roundedBorder)
                                    }
                                    Button(action: { showSyncToken.toggle() }) {
                                        Image(systemName: showSyncToken ? "eye.slash" : "eye")
                                            .foregroundStyle(.secondary)
                                    }
                                    .buttonStyle(.plain)
                                    .onChange(of: syncAccessToken) {
                                        settingsService.syncAccessToken = syncAccessToken.isEmpty ? nil : syncAccessToken
                                    }
                                }
                            }
                        }

                        rowDivider()
                        // Test connection row
                        HStack(spacing: 12) {
                            Button(action: { Task { await testSyncConnection() } }) {
                                HStack {
                                    if isTestingSync {
                                        ProgressView().scaleEffect(0.7).frame(width: 14, height: 14)
                                    } else {
                                        Image(systemName: "checkmark.circle")
                                    }
                                    Text("Test Connection")
                                }
                            }
                            .disabled(isTestingSync || !settingsService.syncConfigured)
                            if let result = syncTestResult {
                                Text(result)
                                    .font(.system(size: 13))
                                    .foregroundStyle(result.hasPrefix("✓") ? .green : .red)
                            }
                            Spacer()
                        }
                        .padding(.horizontal, 16)
                        .padding(.vertical, 10)
                    }
                }
                if settingsService.syncAuthMethod == "password" {
                    Text("⚠️ Many providers (GitHub) no longer support password authentication. Use Access Token instead.")
                        .font(.system(size: 13))
                        .foregroundStyle(.orange)
                        .padding(.horizontal, 4)
                }
                if settingsService.syncAuthMethod == "token" {
                    if let tokenURL = tokenGenerationURL {
                        Link("→ Open \(extractProvider()) Settings to generate a token", destination: URL(string: tokenURL)!)
                            .font(.system(size: 13))
                            .padding(.horizontal, 4)
                    }
                }

                // Sync Options
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Sync Options")
                    formSection {
                        row("Auto-export on save") {
                            Toggle("", isOn: $settingsService.syncAutoExport)
                                .toggleStyle(.switch)
                        }
                        rowDivider()
                        row("Auto-pull on launch") {
                            Toggle("", isOn: $settingsService.syncAutoPull)
                                .toggleStyle(.switch)
                        }
                    }
                }

                // Auto-Save
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Auto-Save")
                    formSection {
                        row("Enable Auto-Save") {
                            Toggle("", isOn: $settingsService.syncAutoSave)
                                .toggleStyle(.switch)
                        }
                        if settingsService.syncAutoSave {
                            rowDivider()
                            row("Min Messages") {
                                HStack {
                                    Slider(value: Binding(
                                        get: { Double(settingsService.syncAutoSaveMinMessages) },
                                        set: { settingsService.syncAutoSaveMinMessages = Int($0) }
                                    ), in: 3...20, step: 1)
                                        .frame(width: 200)
                                    Text("\(settingsService.syncAutoSaveMinMessages)")
                                        .font(.system(size: 14))
                                        .frame(width: 30)
                                }
                            }
                            rowDivider()
                            row("On model switch") {
                                Toggle("", isOn: $settingsService.syncAutoSaveOnModelSwitch)
                                    .toggleStyle(.switch)
                            }
                            rowDivider()
                            row("On app quit") {
                                Toggle("", isOn: $settingsService.syncAutoSaveOnAppQuit)
                                    .toggleStyle(.switch)
                            }
                            rowDivider()
                            row("After idle timeout") {
                                Toggle("", isOn: $settingsService.syncAutoSaveOnIdle)
                                    .toggleStyle(.switch)
                            }
                            if settingsService.syncAutoSaveOnIdle {
                                rowDivider()
                                row("Idle Timeout") {
                                    HStack {
                                        Slider(value: Binding(
                                            get: { Double(settingsService.syncAutoSaveIdleMinutes) },
                                            set: { settingsService.syncAutoSaveIdleMinutes = Int($0) }
                                        ), in: 1...30, step: 1)
                                            .frame(width: 200)
                                        Text("\(settingsService.syncAutoSaveIdleMinutes) min")
                                            .font(.system(size: 14))
                                            .frame(width: 60)
                                    }
                                }
                            }
                        }
                    }
                }
                if settingsService.syncAutoSave {
                    HStack(spacing: 8) {
                        Image(systemName: "exclamationmark.triangle.fill")
                            .foregroundStyle(.orange)
                        Text("Auto-sync can cause conflicts if running on multiple machines simultaneously.")
                            .font(.system(size: 13))
                            .foregroundStyle(.orange)
                    }
                    .padding(.horizontal, 4)
                }

                // Manual Sync
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Manual Sync")
                    formSection {
                        HStack(spacing: 12) {
                            if !gitSync.syncStatus.isCloned {
                                Button {
                                    Task { await cloneRepo() }
                                } label: {
                                    HStack(spacing: 6) {
                                        if isSyncing {
                                            ProgressView().scaleEffect(0.7).frame(width: 16, height: 16)
                                        } else {
                                            Image(systemName: "arrow.down.circle")
                                        }
                                        Text("Initialize Repository")
                                    }
                                    .frame(minWidth: 160)
                                }
                                .disabled(!settingsService.syncConfigured || isSyncing)
                            } else {
                                Button {
                                    Task { await syncNow() }
                                } label: {
                                    HStack(spacing: 6) {
                                        if isSyncing {
                                            ProgressView().scaleEffect(0.7).frame(width: 16, height: 16)
                                        } else {
                                            Image(systemName: "arrow.triangle.2.circlepath")
                                        }
                                        Text("Sync Now")
                                    }
                                    .frame(minWidth: 160)
                                }
                                .disabled(isSyncing)
                            }
                            Spacer()
                        }
                        .padding(.horizontal, 16)
                        .padding(.vertical, 10)
                    }
                }
                if gitSync.syncStatus.isCloned {
                    VStack(alignment: .leading, spacing: 4) {
                        if let lastSync = gitSync.syncStatus.lastSyncTime {
                            Text("Last sync: \(timeAgo(lastSync))")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                        if gitSync.syncStatus.uncommittedChanges > 0 {
                            Text("Uncommitted changes: \(gitSync.syncStatus.uncommittedChanges)")
                                .font(.system(size: 13))
                                .foregroundStyle(.orange)
                        }
                        if let branch = gitSync.syncStatus.currentBranch {
                            Text("Branch: \(branch)")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                        if let status = gitSync.syncStatus.remoteStatus {
                            Text("Remote: \(status)")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                    }
                    .padding(.horizontal, 4)
                }
            }
        }
        .onAppear {
            syncRepoURL = settingsService.syncRepoURL
            syncLocalPath = settingsService.syncLocalPath
            syncUsername = settingsService.syncUsername ?? ""
            syncPassword = settingsService.syncPassword ?? ""
            syncAccessToken = settingsService.syncAccessToken ?? ""

            Task {
                await gitSync.updateStatus()
            }
        }
    }

    // MARK: - Email Tab

    @ViewBuilder
    private var emailTab: some View {
        Group {
            // Security recommendation box
            VStack(alignment: .leading, spacing: 8) {
                HStack(spacing: 8) {
                    Image(systemName: "shield.fill")
                        .foregroundColor(.orange)
                    Text("Security Recommendation")
                        .font(.system(size: settingsService.guiTextSize, weight: .semibold))
                        .foregroundColor(.orange)
                }
                Text("Create a dedicated email account specifically for AI handling. Do NOT use your personal email address.")
                    .font(.system(size: settingsService.guiTextSize))
                    .foregroundColor(.secondary)
                    .fixedSize(horizontal: false, vertical: true)
                Text("Example: oai-bot-x7k2m9p3@gmail.com")
                    .font(.system(size: settingsService.guiTextSize - 1, design: .monospaced))
                    .foregroundColor(.blue)
                    .padding(.vertical, 4)
                    .padding(.horizontal, 8)
                    .background(Color.blue.opacity(0.1))
                    .cornerRadius(4)
            }
            .padding(12)
            .background(Color.orange.opacity(0.05))
            .clipShape(RoundedRectangle(cornerRadius: 10))
            .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.orange.opacity(0.3), lineWidth: 0.5))

            // Enable toggle
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("AI Email Handler")
                formSection {
                    row("Enable Email Handler") {
                        Toggle("", isOn: $settingsService.emailHandlerEnabled)
                            .toggleStyle(.switch)
                    }
                }
            }

            if settingsService.emailHandlerEnabled {
                // AI Configuration
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("AI Configuration")
                    formSection {
                        row("AI Provider") {
                            Picker("", selection: $settingsService.emailHandlerProvider) {
                                ForEach(ProviderRegistry.shared.configuredProviders, id: \.self) { provider in
                                    Text(provider.displayName).tag(provider.rawValue)
                                }
                            }
                            .labelsHidden()
                            .frame(width: 250)
                            .onChange(of: settingsService.emailHandlerProvider) {
                                Task { await loadEmailModels() }
                            }
                        }
                        rowDivider()
                        row("AI Model") {
                            if isLoadingEmailModels {
                                ProgressView().scaleEffect(0.7).frame(width: 250, alignment: .leading)
                            } else if emailAvailableModels.isEmpty {
                                Text("No models available")
                                    .font(.system(size: settingsService.guiTextSize))
                                    .foregroundColor(.secondary)
                                    .frame(width: 250, alignment: .leading)
                            } else {
                                Button(action: { showEmailModelSelector = true }) {
                                    HStack {
                                        Text(emailAvailableModels.first(where: { $0.id == settingsService.emailHandlerModel })?.name ?? "Select model...")
                                            .font(.system(size: settingsService.guiTextSize))
                                            .foregroundColor(.primary)
                                        Spacer()
                                        Image(systemName: "chevron.up.chevron.down")
                                            .font(.system(size: 10))
                                            .foregroundColor(.secondary)
                                    }
                                    .padding(.horizontal, 8)
                                    .padding(.vertical, 4)
                                    .frame(width: 250)
                                    .background(Color(nsColor: .controlBackgroundColor))
                                    .cornerRadius(6)
                                }
                                .buttonStyle(.plain)
                            }
                        }
                    }
                }

                // Email Server
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Email Server")
                    formSection {
                        row("IMAP Host") {
                            TextField("imap.gmail.com", text: Binding(
                                get: { settingsService.emailImapHost ?? "" },
                                set: { settingsService.emailImapHost = $0.isEmpty ? nil : $0 }
                            ))
                            .textFieldStyle(.roundedBorder)
                            .frame(width: 240)
                        }
                        rowDivider()
                        row("SMTP Host") {
                            TextField("smtp.gmail.com", text: Binding(
                                get: { settingsService.emailSmtpHost ?? "" },
                                set: { settingsService.emailSmtpHost = $0.isEmpty ? nil : $0 }
                            ))
                            .textFieldStyle(.roundedBorder)
                            .frame(width: 240)
                        }
                        rowDivider()
                        row("IMAP Port") {
                            TextField("993", text: Binding(
                                get: { String(settingsService.emailImapPort) },
                                set: { settingsService.emailImapPort = Int($0) ?? 993 }
                            ))
                            .textFieldStyle(.roundedBorder)
                            .frame(width: 90)
                        }
                        rowDivider()
                        row("SMTP Port") {
                            TextField("587", text: Binding(
                                get: { String(settingsService.emailSmtpPort) },
                                set: { settingsService.emailSmtpPort = Int($0) ?? 587 }
                            ))
                            .textFieldStyle(.roundedBorder)
                            .frame(width: 90)
                        }
                        rowDivider()
                        row("Username") {
                            TextField("your-email@gmail.com", text: Binding(
                                get: { settingsService.emailUsername ?? "" },
                                set: { settingsService.emailUsername = $0.isEmpty ? nil : $0 }
                            ))
                            .textFieldStyle(.roundedBorder)
                            .frame(width: 240)
                        }
                        rowDivider()
                        row("Password") {
                            HStack {
                                if showEmailPassword {
                                    TextField("", text: Binding(
                                        get: { settingsService.emailPassword ?? "" },
                                        set: { settingsService.emailPassword = $0.isEmpty ? nil : $0 }
                                    ))
                                    .textFieldStyle(.roundedBorder)
                                } else {
                                    SecureField("", text: Binding(
                                        get: { settingsService.emailPassword ?? "" },
                                        set: { settingsService.emailPassword = $0.isEmpty ? nil : $0 }
                                    ))
                                    .textFieldStyle(.roundedBorder)
                                }
                                Button(action: { showEmailPassword.toggle() }) {
                                    Image(systemName: showEmailPassword ? "eye.slash" : "eye")
                                        .foregroundStyle(.secondary)
                                }
                                .buttonStyle(.plain)
                            }
                            .frame(width: 240)
                        }
                        rowDivider()
                        // Test connection
                        HStack(spacing: 12) {
                            Button(action: { Task { await testEmailConnection() } }) {
                                HStack {
                                    if isTestingEmailConnection {
                                        ProgressView().scaleEffect(0.7).frame(width: 14, height: 14)
                                    } else {
                                        Image(systemName: "checkmark.circle")
                                    }
                                    Text("Test Connection")
                                }
                            }
                            .disabled(isTestingEmailConnection || !settingsService.emailServerConfigured)
                            if let result = emailConnectionTestResult {
                                Text(result)
                                    .font(.system(size: settingsService.guiTextSize - 1))
                                    .foregroundColor(result.hasPrefix("✓") ? .green : .red)
                            }
                            Spacer()
                        }
                        .padding(.horizontal, 16)
                        .padding(.vertical, 10)
                    }
                }
                Text("💡 For Gmail, use an App Password. Google Account > Security > 2-Step Verification > App passwords.")
                    .font(.system(size: settingsService.guiTextSize - 1))
                    .foregroundColor(.secondary)
                    .fixedSize(horizontal: false, vertical: true)
                    .padding(.horizontal, 4)

                // Email Trigger
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Email Trigger")
                    formSection {
                        row("Subject Identifier") {
                            TextField("", text: $settingsService.emailSubjectIdentifier)
                                .textFieldStyle(.roundedBorder)
                                .frame(width: 200)
                        }
                    }
                }
                Text("Only emails with this text in the subject line will be processed. Example: \"[OAIBOT] What's the weather?\"")
                    .font(.system(size: settingsService.guiTextSize - 1))
                    .foregroundColor(.secondary)
                    .fixedSize(horizontal: false, vertical: true)
                    .padding(.horizontal, 4)

                // Rate Limiting
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Rate Limiting")
                    formSection {
                        row("Enable Rate Limit") {
                            Toggle("", isOn: $settingsService.emailRateLimitEnabled)
                                .toggleStyle(.switch)
                        }
                        if settingsService.emailRateLimitEnabled {
                            rowDivider()
                            row("Max Emails Per Hour") {
                                HStack {
                                    Slider(value: Binding(
                                        get: { Double(settingsService.emailRateLimitPerHour) },
                                        set: { settingsService.emailRateLimitPerHour = Int($0) }
                                    ), in: 1...100, step: 1)
                                        .frame(width: 200)
                                    Text(settingsService.emailRateLimitPerHour == 100 ? "Unlimited" : "\(settingsService.emailRateLimitPerHour)")
                                        .font(.system(size: settingsService.guiTextSize))
                                        .frame(width: 70, alignment: .trailing)
                                }
                            }
                        }
                    }
                }

                // Response Settings
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Response Settings")
                    formSection {
                        row("Max Response Tokens") {
                            HStack {
                                Slider(value: Binding(
                                    get: { Double(settingsService.emailMaxTokens) },
                                    set: { settingsService.emailMaxTokens = Int($0) }
                                ), in: 100...8000, step: 100)
                                    .frame(width: 200)
                                Text("\(settingsService.emailMaxTokens)")
                                    .font(.system(size: settingsService.guiTextSize))
                                    .frame(width: 60, alignment: .trailing)
                            }
                        }
                        rowDivider()
                        row("Enable Online Mode") {
                            Toggle("", isOn: $settingsService.emailOnlineMode)
                                .toggleStyle(.switch)
                        }
                    }
                }
                Text("~750 tokens ≈ 500 words. Online mode allows web search in responses.")
                    .font(.system(size: settingsService.guiTextSize - 1))
                    .foregroundColor(.secondary)
                    .padding(.horizontal, 4)

                // Custom System Prompt
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("System Prompt (Optional)")
                    formSection {
                        VStack(alignment: .leading, spacing: 8) {
                            HStack(alignment: .top, spacing: 8) {
                                Image(systemName: "exclamationmark.triangle.fill")
                                    .foregroundColor(.orange)
                                Text("Email handler uses ONLY its own system prompt, completely isolated from your main chat settings. A custom prompt below will override the defaults.")
                                    .font(.system(size: settingsService.guiTextSize - 1))
                                    .foregroundColor(.secondary)
                                    .fixedSize(horizontal: false, vertical: true)
                            }

                            HStack {
                                Text("Email Handler System Prompt")
                                    .font(.system(size: settingsService.guiTextSize - 1, weight: .medium))
                                    .foregroundColor(.secondary)
                                Spacer()
                                if !emailHandlerSystemPrompt.isEmpty {
                                    Button("Clear") {
                                        emailHandlerSystemPrompt = ""
                                        settingsService.emailHandlerSystemPrompt = nil
                                    }
                                    .font(.system(size: settingsService.guiTextSize - 1))
                                }
                            }

                            TextEditor(text: $emailHandlerSystemPrompt)
                                .font(.system(size: settingsService.guiTextSize, design: .monospaced))
                                .frame(height: 100)
                                .padding(8)
                                .background(Color(NSColor.textBackgroundColor))
                                .cornerRadius(6)
                                .overlay(RoundedRectangle(cornerRadius: 6).stroke(Color.secondary.opacity(0.2), lineWidth: 1))
                                .onChange(of: emailHandlerSystemPrompt) {
                                    settingsService.emailHandlerSystemPrompt = emailHandlerSystemPrompt.isEmpty ? nil : emailHandlerSystemPrompt
                                }

                            if emailHandlerSystemPrompt.isEmpty {
                                Text("Leave empty to use the default email handler system prompt.")
                                    .font(.system(size: settingsService.guiTextSize - 2))
                                    .foregroundColor(.secondary)
                                    .fixedSize(horizontal: false, vertical: true)
                            } else {
                                Text("⚠️ Custom prompt active — only this prompt will be sent to the model.")
                                    .font(.system(size: settingsService.guiTextSize - 2))
                                    .foregroundColor(.orange)
                                    .fixedSize(horizontal: false, vertical: true)
                            }
                        }
                        .padding(.horizontal, 16)
                        .padding(.vertical, 12)
                    }
                }

                // Email Log + MCP notice
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Activity")
                    formSection {
                        row("Email Log") {
                            Button(action: { showEmailLog = true }) {
                                HStack {
                                    Image(systemName: "envelope.badge.fill")
                                    Text("View Email Log")
                                }
                            }
                        }
                    }
                }

                // MCP Access Notice
                VStack(alignment: .leading, spacing: 8) {
                    HStack(spacing: 8) {
                        Image(systemName: "info.circle.fill")
                            .foregroundColor(.blue)
                        Text("File Access Permissions")
                            .font(.system(size: settingsService.guiTextSize, weight: .semibold))
                            .foregroundColor(.blue)
                    }
                    Text("Email tasks have READ-ONLY access to MCP folders. The AI cannot write, delete, or modify files when processing emails.")
                        .font(.system(size: settingsService.guiTextSize))
                        .foregroundColor(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
                .padding(12)
                .background(Color.blue.opacity(0.05))
                .clipShape(RoundedRectangle(cornerRadius: 10))
                .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.blue.opacity(0.3), lineWidth: 0.5))
            }
        }
        .onAppear {
            emailHandlerSystemPrompt = settingsService.emailHandlerSystemPrompt ?? ""
            Task {
                await loadEmailModels()
            }
        }
        .sheet(isPresented: $showEmailModelSelector) {
            ModelSelectorView(
                models: emailAvailableModels.sorted { $0.name.localizedStandardCompare($1.name) == .orderedAscending },
                selectedModel: emailAvailableModels.first(where: { $0.id == settingsService.emailHandlerModel })
            ) { selectedModel in
                settingsService.emailHandlerModel = selectedModel.id
                showEmailModelSelector = false
            }
        }
    }

    // MARK: - Shortcuts Tab

    @ViewBuilder
    private var shortcutsTab: some View {
        ShortcutsTabContent()
    }

    // MARK: - Agent Skills Tab

    @ViewBuilder
    private var agentSkillsTab: some View {
        AgentSkillsTabContent()
    }

    // MARK: - Paperless Tab

    @ViewBuilder
    private var paperlessTab: some View {
        VStack(alignment: .leading, spacing: 20) {
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Paperless-NGX")
                formSection {
                    row("Enable Paperless") {
                        Toggle("", isOn: $settingsService.paperlessEnabled)
                            .toggleStyle(.switch)
                    }
                }
            }

            if settingsService.paperlessEnabled {
                VStack(alignment: .leading, spacing: 6) {
                    sectionHeader("Connection")
                    formSection {
                        row("Base URL") {
                            TextField("https://paperless.yourdomain.com", text: $paperlessURL)
                                .textFieldStyle(.roundedBorder)
                                .frame(maxWidth: 300)
                                .onSubmit { settingsService.paperlessURL = paperlessURL }
                                .onChange(of: paperlessURL) { _, new in settingsService.paperlessURL = new }
                        }
                        rowDivider()
                        row("API Token") {
                            HStack(spacing: 6) {
                                if showPaperlessToken {
                                    TextField("", text: $paperlessToken)
                                        .textFieldStyle(.roundedBorder)
                                        .frame(maxWidth: 240)
                                        .onSubmit { settingsService.paperlessAPIToken = paperlessToken.isEmpty ? nil : paperlessToken }
                                        .onChange(of: paperlessToken) { _, new in
                                            settingsService.paperlessAPIToken = new.isEmpty ? nil : new
                                        }
                                } else {
                                    SecureField("", text: $paperlessToken)
                                        .textFieldStyle(.roundedBorder)
                                        .frame(maxWidth: 240)
                                        .onSubmit { settingsService.paperlessAPIToken = paperlessToken.isEmpty ? nil : paperlessToken }
                                        .onChange(of: paperlessToken) { _, new in
                                            settingsService.paperlessAPIToken = new.isEmpty ? nil : new
                                        }
                                }
                                Button(showPaperlessToken ? "Hide" : "Show") {
                                    showPaperlessToken.toggle()
                                }
                                .buttonStyle(.borderless)
                                .font(.system(size: 13))
                            }
                        }
                        rowDivider()
                        HStack(spacing: 12) {
                            Button(action: { Task { await testPaperlessConnection() } }) {
                                HStack {
                                    if isTestingPaperless {
                                        ProgressView().scaleEffect(0.7).frame(width: 14, height: 14)
                                    } else {
                                        Image(systemName: "checkmark.circle")
                                    }
                                    Text("Test Connection")
                                }
                            }
                            .disabled(isTestingPaperless || !settingsService.paperlessConfigured)
                            if let result = paperlessTestResult {
                                Text(result)
                                    .font(.system(size: 13))
                                    .foregroundStyle(result.hasPrefix("✓") ? .green : .red)
                            }
                            Spacer()
                        }
                        .padding(.horizontal, 16)
                        .padding(.vertical, 10)
                    }
                }

                VStack(alignment: .leading, spacing: 4) {
                    Text("How to get your API token:")
                        .font(.system(size: 13, weight: .medium))
                    Text("1. Open Paperless-NGX → Settings → API Tokens")
                    Text("2. Create or copy your token")
                    Text("3. Paste it above")
                }
                .font(.system(size: 13))
                .foregroundStyle(.secondary)
                .padding(.horizontal, 4)
            }
        }
        .onAppear {
            paperlessURL = settingsService.paperlessURL
            paperlessToken = settingsService.paperlessAPIToken ?? ""
        }
    }

    private func testPaperlessConnection() async {
        isTestingPaperless = true
        paperlessTestResult = nil
        let result = await PaperlessService.shared.testConnection()
        await MainActor.run {
            switch result {
            case .success(let msg):
                paperlessTestResult = "✓ \(msg)"
            case .failure(let err):
                paperlessTestResult = "✗ \(err.localizedDescription)"
            }
            isTestingPaperless = false
        }
    }

    // MARK: - Backup Tab

    @ViewBuilder
    private var backupTab: some View {
        VStack(alignment: .leading, spacing: 20) {
            // Warning notice
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("iCloud Drive Backup")
                HStack(alignment: .top, spacing: 8) {
                    Image(systemName: "exclamationmark.triangle.fill")
                        .foregroundStyle(.orange)
                        .font(.system(size: 14))
                    Text("API keys and credentials are **not** included in the backup. You will need to re-enter them after restoring on a new machine.")
                        .font(.system(size: 13))
                        .fixedSize(horizontal: false, vertical: true)
                }
                .padding(.horizontal, 4)
                .padding(.top, 2)
            }

            // Status
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Status")
                formSection {
                    row("iCloud Drive") {
                        HStack(spacing: 6) {
                            Circle()
                                .fill(backupService.iCloudAvailable ? Color.green : Color.orange)
                                .frame(width: 8, height: 8)
                            Text(backupService.iCloudAvailable ? "Available" : "Not available — using Downloads")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                    }
                    rowDivider()
                    row("Last Backup") {
                        if let date = backupService.lastBackupDate {
                            Text(formatBackupDate(date))
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        } else {
                            Text("Never")
                                .font(.system(size: 13))
                                .foregroundStyle(.secondary)
                        }
                    }
                }
            }

            // Actions
            VStack(alignment: .leading, spacing: 6) {
                sectionHeader("Actions")
                formSection {
                    HStack(spacing: 12) {
                        Button(action: { Task { await performBackup() } }) {
                            HStack(spacing: 6) {
                                if isExporting {
                                    ProgressView().scaleEffect(0.7).frame(width: 14, height: 14)
                                } else {
                                    Image(systemName: "icloud.and.arrow.up")
                                }
                                Text("Back Up Now")
                            }
                        }
                        .disabled(isExporting || isImporting)

                        Button(action: { showRestoreFilePicker = true }) {
                            HStack(spacing: 6) {
                                if isImporting {
                                    ProgressView().scaleEffect(0.7).frame(width: 14, height: 14)
                                } else {
                                    Image(systemName: "icloud.and.arrow.down")
                                }
                                Text("Restore from File…")
                            }
                        }
                        .disabled(isExporting || isImporting)

                        Spacer()
                    }
                    .padding(.horizontal, 16)
                    .padding(.vertical, 10)

                    if let msg = backupMessage {
                        rowDivider()
                        HStack(spacing: 6) {
                            Image(systemName: backupMessageIsError ? "xmark.circle.fill" : "checkmark.circle.fill")
                                .foregroundStyle(backupMessageIsError ? .red : .green)
                            Text(msg)
                                .font(.system(size: 13))
                                .foregroundStyle(backupMessageIsError ? .red : .primary)
                                .fixedSize(horizontal: false, vertical: true)
                        }
                        .padding(.horizontal, 16)
                        .padding(.vertical, 8)
                    }
                }
            }

            // Backup location
            if let url = backupService.lastBackupURL {
                VStack(alignment: .leading, spacing: 4) {
                    Text("Backup location:")
                        .font(.system(size: 13, weight: .medium))
                    Text(url.path.replacingOccurrences(
                        of: FileManager.default.homeDirectoryForCurrentUser.path,
                        with: "~"))
                        .font(.system(size: 12))
                        .foregroundStyle(.secondary)
                        .textSelection(.enabled)
                }
                .padding(.horizontal, 4)
            }
        }
        .onAppear {
            backupService.checkForExistingBackup()
        }
    }

    private func performBackup() async {
        await MainActor.run {
            isExporting = true
            backupMessage = nil
        }
        do {
            let url = try await backupService.exportSettings()
            let shortPath = url.path.replacingOccurrences(
                of: FileManager.default.homeDirectoryForCurrentUser.path,
                with: "~")
            await MainActor.run {
                backupMessage = "Backup saved to \(shortPath)"
                backupMessageIsError = false
                isExporting = false
            }
        } catch {
            await MainActor.run {
                backupMessage = error.localizedDescription
                backupMessageIsError = true
                isExporting = false
            }
        }
    }

    private func performRestore(from url: URL) async {
        await MainActor.run {
            isImporting = true
            backupMessage = nil
        }
        do {
            _ = url.startAccessingSecurityScopedResource()
            defer { url.stopAccessingSecurityScopedResource() }
            try await backupService.importSettings(from: url)
            await MainActor.run {
                backupMessage = "Settings restored. Re-enter your API keys to resume using oAI."
                backupMessageIsError = false
                isImporting = false
            }
        } catch {
            await MainActor.run {
                backupMessage = error.localizedDescription
                backupMessageIsError = true
                isImporting = false
            }
        }
    }

    private func formatBackupDate(_ date: Date) -> String {
        let cal = Calendar.current
        if cal.isDateInToday(date) {
            let tf = DateFormatter()
            tf.dateFormat = "HH:mm"
            return "Today \(tf.string(from: date))"
        }
        let df = DateFormatter()
        df.dateFormat = "dd.MM.yyyy HH:mm"
        return df.string(from: date)
    }

    // MARK: - Tab Navigation

    private func tabButton(_ tag: Int, icon: String, label: LocalizedStringKey, beta: Bool = false) -> some View {
        Button(action: { selectedTab = tag }) {
            VStack(spacing: 3) {
                ZStack(alignment: .topTrailing) {
                    Image(systemName: icon)
                        .font(.system(size: 22))
                        .frame(height: 28)
                        .foregroundStyle(selectedTab == tag ? .blue : .secondary)
                    if beta {
                        Text("β")
                            .font(.system(size: 8, weight: .bold))
                            .foregroundStyle(.white)
                            .padding(.horizontal, 3)
                            .padding(.vertical, 1)
                            .background(Color.orange)
                            .clipShape(Capsule())
                            .offset(x: 6, y: -2)
                    }
                }
                Text(label)
                    .font(.system(size: 11))
                    .foregroundStyle(selectedTab == tag ? .blue : .secondary)
            }
            .frame(minWidth: 68)
            .padding(.vertical, 6)
            .padding(.horizontal, 6)
            .background(selectedTab == tag ? Color.blue.opacity(0.1) : Color.clear)
            .clipShape(RoundedRectangle(cornerRadius: 8))
        }
        .buttonStyle(.plain)
    }

    private func tabTitle(_ tag: Int) -> LocalizedStringKey {
        switch tag {
        case 0: return "General"
        case 1: return "MCP"
        case 2: return "Appearance"
        case 3: return "Advanced"
        case 4: return "Sync"
        case 5: return "Email"
        case 6: return "Shortcuts"
        case 7: return "Skills"
        case 8: return "Paperless"
        case 9: return "Backup"
        default: return "Settings"
        }
    }

    // MARK: - Reasoning Helpers

    private var reasoningEffortDescription: LocalizedStringKey {
        switch settingsService.reasoningEffort {
        case "high":    return "Uses ~80% of max tokens for reasoning — best for hard problems"
        case "medium":  return "Uses ~50% of max tokens for reasoning — balanced default"
        case "low":     return "Uses ~20% of max tokens for reasoning — faster, cheaper"
        case "minimal": return "Uses ~10% of max tokens for reasoning — lightest thinking"
        default:        return "Uses ~50% of max tokens for reasoning — balanced default"
        }
    }

    // MARK: - Layout Helpers

    private func row<Content: View>(_ label: LocalizedStringKey, @ViewBuilder content: () -> Content) -> some View {
        HStack(alignment: .center, spacing: 12) {
            Text(label).font(.system(size: 14))
            Spacer()
            content()
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 10)
    }

    private func sectionHeader(_ title: LocalizedStringKey) -> some View {
        Text(title)
            .font(.system(size: 12, weight: .semibold))
            .foregroundStyle(.secondary)
            .textCase(.uppercase)
            .padding(.horizontal, 4)
    }

    private func formSection<Content: View>(@ViewBuilder content: () -> Content) -> some View {
        VStack(spacing: 0) { content() }
            .background(.regularMaterial)
            .clipShape(RoundedRectangle(cornerRadius: 10))
            .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.primary.opacity(0.10), lineWidth: 0.5))
    }

    private func rowDivider() -> some View {
        Divider().padding(.leading, 16)
    }

    private func abbreviatePath(_ path: String) -> String {
        let home = NSHomeDirectory()
        if path.hasPrefix(home) {
            return "~" + path.dropFirst(home.count)
        }
        return path
    }

    // MARK: - Email Helpers

    private func loadEmailModels() async {
        guard settingsService.emailHandlerEnabled else {
            emailAvailableModels = []
            return
        }

        let providerRawValue = settingsService.emailHandlerProvider
        guard let providerType = Settings.Provider(rawValue: providerRawValue),
              let provider = ProviderRegistry.shared.getProvider(for: providerType) else {
            emailAvailableModels = []
            return
        }

        isLoadingEmailModels = true
        defer { isLoadingEmailModels = false }

        do {
            let models = try await provider.listModels()
            emailAvailableModels = models

            // If current model is not in the list, select the first one
            if !models.contains(where: { $0.id == settingsService.emailHandlerModel }) {
                if let firstModel = models.first {
                    settingsService.emailHandlerModel = firstModel.id
                }
            }
        } catch {
            Log.ui.error("Failed to load email models: \(error.localizedDescription)")
            emailAvailableModels = []
        }
    }

    private func testEmailConnection() async {
        isTestingEmailConnection = true
        emailConnectionTestResult = nil

        do {
            let result = try await EmailService.shared.testConnection()
            emailConnectionTestResult = "✓ \(result)"
        } catch {
            emailConnectionTestResult = "✗ \(error.localizedDescription)"
        }

        isTestingEmailConnection = false
    }

    // MARK: - Sync Helpers

    private func testSyncConnection() async {
        isTestingSync = true
        syncTestResult = nil

        do {
            let result = try await gitSync.testConnection()
            syncTestResult = "✓ \(result)"
        } catch {
            syncTestResult = "✗ \(error.localizedDescription)"
        }

        isTestingSync = false
    }

    private var syncStatusIcon: String {
        guard settingsService.syncEnabled else { return "externaldrive.slash" }
        guard settingsService.syncConfigured else { return "exclamationmark.triangle" }
        guard gitSync.syncStatus.isCloned else { return "externaldrive.badge.questionmark" }
        return "externaldrive.badge.checkmark"
    }

    private var syncStatusColor: Color {
        guard settingsService.syncEnabled else { return .secondary }
        guard settingsService.syncConfigured else { return .orange }
        guard gitSync.syncStatus.isCloned else { return .orange }
        return .green
    }

    private var syncStatusText: LocalizedStringKey {
        guard settingsService.syncEnabled else { return "Disabled" }
        guard settingsService.syncConfigured else { return "Not configured" }
        guard gitSync.syncStatus.isCloned else { return "Not cloned" }
        return "Ready"
    }

    private func cloneRepo() async {
        do {
            try await gitSync.cloneRepository()
            syncTestResult = "✓ Repository cloned successfully"
        } catch {
            syncTestResult = "✗ \(error.localizedDescription)"
        }
    }

    private func exportConversations() async {
        do {
            try await gitSync.exportAllConversations()
            syncTestResult = "✓ Conversations exported"
        } catch {
            syncTestResult = "✗ \(error.localizedDescription)"
        }
    }

    private func pushToGit() async {
        do {
            // First export conversations
            try await gitSync.exportAllConversations()
            // Then push
            try await gitSync.push()
            syncTestResult = "✓ Changes pushed successfully"
        } catch {
            syncTestResult = "✗ \(error.localizedDescription)"
        }
    }

    private func pullFromGit() async {
        do {
            try await gitSync.pull()
            syncTestResult = "✓ Changes pulled successfully"
        } catch {
            syncTestResult = "✗ \(error.localizedDescription)"
        }
    }

    private func importConversations() async {
        do {
            let result = try await gitSync.importAllConversations()
            syncTestResult = "✓ Imported \(result.imported) conversations (skipped \(result.skipped) duplicates)"
        } catch {
            syncTestResult = "✗ \(error.localizedDescription)"
        }
    }

    private func syncNow() async {
        isSyncing = true
        syncTestResult = nil

        do {
            // Step 1: Export all conversations
            syncTestResult = "Exporting conversations..."
            try await gitSync.exportAllConversations()

            // Step 2: Pull from remote
            syncTestResult = "Pulling changes..."
            try await gitSync.pull()

            // Step 3: Import any new conversations
            syncTestResult = "Importing conversations..."
            let result = try await gitSync.importAllConversations()

            // Step 4: Push to remote
            syncTestResult = "Pushing changes..."
            try await gitSync.push()

            // Success
            await gitSync.updateStatus()
            syncTestResult = "✓ Sync complete: \(result.imported) imported, \(result.skipped) skipped"
        } catch {
            syncTestResult = "✗ Sync failed: \(error.localizedDescription)"
        }

        isSyncing = false
    }

    private var tokenGenerationURL: String? {
        let url = settingsService.syncRepoURL.lowercased()
        if url.contains("github.com") {
            return "https://github.com/settings/tokens"
        } else if url.contains("gitlab.com") {
            return "https://gitlab.com/-/profile/personal_access_tokens"
        } else if url.contains("gitea") {
            return extractProvider() + "/user/settings/applications"
        } else {
            return nil
        }
    }

    private func extractProvider() -> String {
        let url = settingsService.syncRepoURL
        if url.contains("github.com") {
            return "GitHub"
        } else if url.contains("gitlab.com") {
            return "GitLab"
        } else if url.contains("gitea") {
            return "Gitea"
        } else {
            return "Git repository"
        }
    }

    private func timeAgo(_ date: Date) -> String {
        let formatter = RelativeDateTimeFormatter()
        formatter.unitsStyle = .full
        return formatter.localizedString(for: date, relativeTo: .now)
    }
}

#Preview {
    SettingsView()
}
