//
//  ConversationListView.swift
//  kordophone2
//
//  Created by James Magahern on 8/24/25.
//

import SwiftUI

struct ConversationListView: View
{
    @Binding var model: ViewModel
    @Environment(\.xpcClient) private var xpcClient
    @Environment(\.openWindow) private var openWindow

    var body: some View {
        List($model.conversations, selection: $model.selectedConversation) { conv in
            let isUnread = conv.wrappedValue.unreadCount > 0
            
            HStack(spacing: 0.0) {
                if isUnread {
                    Image(systemName: "circlebadge.fill")
                        .foregroundStyle(.tint)
                        .frame(width: 10.0)
                } else {
                    Rectangle()
                        .foregroundStyle(.clear)
                        .frame(width: 10.0)
                }
                
                VStack(alignment: .leading) {
                    Text(conv.wrappedValue.displayName)
                        .bold()
                    
                    Text(conv.wrappedValue.messagePreview)
                        .foregroundStyle(.secondary)
                }
                .padding(8.0)
            }
            .id(conv.id)
        }
        .listStyle(.sidebar)
        .task { await watchForConversationListChanges() }
        .task { await model.triggerSync() }
    }
    
    private func watchForConversationListChanges() async  {
        for await event in xpcClient.eventStream() {
            switch event {
                case .conversationsUpdated:
                    model.setNeedsReload()
                case .messagesUpdated(_):
                    await model.triggerSync()
                case .updateStreamReconnected:
                    await model.triggerSync()
                default:
                    break
            }
        }
    }
    
    // MARK: - Types
    
    @Observable
    class ViewModel
    {
        var conversations: [Display.Conversation]
        var selectedConversation: Display.Conversation.ID?

        private var needsReload: Bool = true
        private let client = XPCClient()
        
        public init(conversations: [Display.Conversation] = []) {
            self.conversations = conversations
            self.selectedConversation = nil
            setNeedsReload()
        }
        
        func triggerSync() async {
            do {
                try await client.syncConversationList()
            } catch {
                print("Conversation List Sync Error: \(error)")
            }
        }
        
        func setNeedsReload() {
            needsReload = true
            Task { @MainActor [weak self] in
                guard let self else { return }
                await reloadConversations()
            }
        }

        func reloadConversations() async {
            guard needsReload else { return }
            needsReload = false

            do {
                
                let clientConversations = try await client.getConversations()
                    .map { Display.Conversation(from: $0) }
                
                self.conversations = clientConversations

                let unreadConversations = clientConversations.filter(\.isUnread)
                await MainActor.run {
                    NSApplication.shared.dockTile.badgeLabel = unreadConversations.isEmpty ? nil : "\(unreadConversations.count)"
                }
            } catch {
                print("Error reloading conversations: \(error)")
            }
        }
    }
}

#Preview {
    @Previewable @State var viewModel = ConversationListView.ViewModel(conversations: [
        .init(id: "asdf", name: "Cool", participants: ["me"], messagePreview: "Hello there"),
        .init(id: "gjkl", name: "Nice", participants: ["me"], messagePreview: "How are you"),
    ])
    
    ConversationListView(model: $viewModel)
}
