//
//  CombineConversationsSheet.swift
//  Confab
//
//  Combine 2+ saved conversations into one, optionally using AI to merge content
//
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
// Copyright (C) 2026 Rune Olsen
//
// This file is part of Confab.
//
// Confab is licensed under the PolyForm Noncommercial License 1.0.0.
// You may use, study, modify, and share it for any noncommercial
// purpose. Commercial use — including selling Confab or any part of
// it, standalone or bundled into another product or service —
// requires a separate commercial license from the copyright holder.
//
// See the LICENSE file or
// <https://polyformproject.org/licenses/noncommercial/1.0.0> for
// the full license text. For commercial licensing, contact Rune
// Olsen via <https://confab.no>.


import SwiftUI

struct CombineConversationsSheet: View {
    @Environment(\.dismiss) var dismiss

    let conversations: [Conversation]
    var onCompleted: (Conversation) -> Void

    @State private var name: String
    @State private var mode: CombineMode = .simple
    @State private var deleteOriginals = false
    @State private var isProcessing = false
    @State private var errorMessage: String?
    @State private var mergeModel: ModelInfo?
    @State private var mergeProvider: Settings.Provider
    @State private var mergeModels: [ModelInfo] = []
    @State private var isLoadingMergeModels = false
    @State private var showModelPicker = false

    private let settings = SettingsService.shared

    init(conversations: [Conversation], onCompleted: @escaping (Conversation) -> Void) {
        self.conversations = conversations
        self.onCompleted = onCompleted
        let joined = conversations.map(\.name).joined(separator: " + ")
        _name = State(initialValue: String(joined.prefix(80)))
        _mergeProvider = State(initialValue: SettingsService.shared.defaultProvider)
    }

    private var mergeModelLabel: String? {
        guard let mergeModel else { return nil }
        return "\(mergeProvider.displayName) / \(mergeModel.name)"
    }

    private var isValid: Bool {
        !name.trimmingCharacters(in: .whitespaces).isEmpty
            && conversations.count >= 2
            && (mode == .simple || mergeModelLabel != nil)
    }

    var body: some View {
        VStack(spacing: 0) {
            HStack {
                Text("Combine Conversations")
                    .font(.system(size: 18, weight: .bold))
                Spacer()
                Button { dismiss() } label: {
                    Image(systemName: "xmark.circle.fill")
                        .font(.title2).foregroundStyle(.secondary)
                }
                .buttonStyle(.plain)
                .keyboardShortcut(.escape, modifiers: [])
                .disabled(isProcessing)
            }
            .padding(.horizontal, 24).padding(.top, 20).padding(.bottom, 16)

            Divider()

            ScrollView {
                VStack(alignment: .leading, spacing: 16) {
                    VStack(alignment: .leading, spacing: 6) {
                        Text("Combining \(conversations.count) conversations").font(.system(size: 13, weight: .semibold))
                        VStack(alignment: .leading, spacing: 4) {
                            ForEach(conversations) { conversation in
                                Label("\(conversation.name) (\(conversation.messageCount) messages)", systemImage: "bubble.left.and.bubble.right")
                                    .font(.system(size: 12))
                                    .foregroundStyle(.secondary)
                            }
                        }
                    }

                    VStack(alignment: .leading, spacing: 6) {
                        Text("New conversation name").font(.system(size: 13, weight: .semibold))
                        TextField("Name", text: $name)
                            .textFieldStyle(.roundedBorder)
                            .disabled(isProcessing)
                    }

                    VStack(alignment: .leading, spacing: 8) {
                        Text("Merge method").font(.system(size: 13, weight: .semibold))
                        Picker("", selection: $mode) {
                            Text("Simple Merge").tag(CombineMode.simple)
                            Text("AI-Assisted Merge").tag(CombineMode.ai)
                        }
                        .pickerStyle(.segmented)
                        .labelsHidden()
                        .disabled(isProcessing)

                        if mode == .simple {
                            Text("Messages from all selected conversations are combined in chronological order.")
                                .font(.caption).foregroundStyle(.secondary)
                        } else {
                            Text("A model reads all the source messages and rewrites them into one coherent, de-duplicated conversation.")
                                .font(.caption).foregroundStyle(.secondary)
                            HStack(spacing: 8) {
                                if let label = mergeModelLabel {
                                    Label(label, systemImage: "cpu")
                                        .font(.caption).foregroundStyle(.secondary)
                                } else {
                                    Label("No model selected", systemImage: "exclamationmark.triangle.fill")
                                        .font(.caption).foregroundStyle(.orange)
                                }

                                Menu {
                                    ForEach(ProviderRegistry.shared.configuredProviders, id: \.self) { p in
                                        Button {
                                            switchMergeProvider(to: p)
                                        } label: {
                                            HStack {
                                                Image(systemName: p.iconName)
                                                Text(p.displayName)
                                                if p == mergeProvider { Image(systemName: "checkmark") }
                                            }
                                        }
                                    }
                                } label: {
                                    HStack(spacing: 4) {
                                        Image(systemName: mergeProvider.iconName)
                                        Text(mergeProvider.displayName)
                                        Image(systemName: "chevron.up.chevron.down")
                                            .font(.system(size: 7))
                                            .opacity(0.7)
                                    }
                                    .font(.caption)
                                    .foregroundColor(.white)
                                    .padding(.horizontal, 6)
                                    .padding(.vertical, 3)
                                    .background(Color.providerColor(mergeProvider))
                                    .cornerRadius(4)
                                }
                                .menuStyle(.borderlessButton)
                                .fixedSize()
                                .disabled(isProcessing || isLoadingMergeModels)

                                Button("Change Model…") {
                                    showModelPicker = true
                                }
                                .buttonStyle(.link)
                                .font(.caption)
                                .disabled(isProcessing || isLoadingMergeModels || mergeModels.isEmpty)

                                if isLoadingMergeModels {
                                    ProgressView().controlSize(.mini)
                                }
                            }
                        }
                    }

                    Toggle("Delete original conversations after combining", isOn: $deleteOriginals)
                        .toggleStyle(.checkbox)
                        .disabled(isProcessing)

                    if let errorMessage {
                        HStack(alignment: .top, spacing: 8) {
                            Image(systemName: "xmark.octagon.fill").foregroundStyle(.red)
                            Text(errorMessage).font(.caption)
                        }
                        .padding(10)
                        .background(.red.opacity(0.08), in: RoundedRectangle(cornerRadius: 8))
                    }
                }
                .padding(.horizontal, 24).padding(.vertical, 16)
            }

            Divider()

            HStack {
                Button("Cancel") { dismiss() }
                    .buttonStyle(.bordered)
                    .disabled(isProcessing)
                Spacer()
                if isProcessing {
                    ProgressView().controlSize(.small)
                    Text("Combining…").font(.caption).foregroundStyle(.secondary)
                }
                Button("Combine") {
                    combine()
                }
                .buttonStyle(.borderedProminent)
                .disabled(!isValid || isProcessing)
                .keyboardShortcut(.return, modifiers: [.command])
            }
            .padding(.horizontal, 24).padding(.vertical, 12)
        }
        .frame(minWidth: 520, idealWidth: 560, minHeight: 460, idealHeight: 520)
        .task {
            await loadMergeModels()
            if let defaultModel = settings.defaultModel {
                mergeModel = mergeModels.first(where: { $0.id == defaultModel })
            }
        }
        .sheet(isPresented: $showModelPicker) {
            ModelSelectorView(
                models: mergeModels,
                selectedModel: mergeModel,
                onSelect: { model in
                    mergeModel = model
                    showModelPicker = false
                }
            )
        }
    }

    private func switchMergeProvider(to newProvider: Settings.Provider) {
        guard newProvider != mergeProvider else { return }
        mergeProvider = newProvider
        mergeModel = nil
        mergeModels = []
        Task { await loadMergeModels() }
    }

    private func loadMergeModels() async {
        guard let provider = ProviderRegistry.shared.getProvider(for: mergeProvider) else {
            mergeModels = []
            return
        }
        isLoadingMergeModels = true
        defer { isLoadingMergeModels = false }
        do {
            mergeModels = try await provider.listModels()
        } catch {
            Log.api.error("Failed to load models for merge provider \(mergeProvider.rawValue): \(error.localizedDescription)")
            mergeModels = []
        }
    }

    private func combine() {
        isProcessing = true
        errorMessage = nil
        let ids = conversations.map(\.id)
        let trimmedName = name.trimmingCharacters(in: .whitespaces)
        let selectedMode = mode
        let shouldDeleteOriginals = deleteOriginals
        let selectedModelId = mergeModel?.id
        let selectedProvider = mergeModel != nil ? mergeProvider : nil

        Task {
            do {
                let newConversation = try await ConversationMergeService.merge(
                    conversationIds: ids,
                    name: trimmedName,
                    mode: selectedMode,
                    mergeModelId: selectedModelId,
                    mergeProvider: selectedProvider,
                    deleteOriginals: shouldDeleteOriginals
                )
                await MainActor.run {
                    isProcessing = false
                    onCompleted(newConversation)
                    dismiss()
                }
            } catch {
                await MainActor.run {
                    isProcessing = false
                    errorMessage = error.localizedDescription
                }
            }
        }
    }
}
