import AppKit
import SwiftUI

@MainActor
struct ChatView: View {
    @ObservedObject private var session: AppSession
    @StateObject private var viewModel: ChatViewModel

    init(session: AppSession) {
        self.session = session
        _viewModel = StateObject(wrappedValue: ChatViewModel(session: session))
    }

    init() {
        self.init(session: AppSession.shared)
    }

    var body: some View {
        VStack(spacing: 0) {
            ScrollViewReader { proxy in
                ScrollView {
                    LazyVStack(spacing: 12) {
                        ForEach(session.messages) { message in
                            MessageBubble(
                                message: message,
                                isSent: message.from == KeychainStore.installationID
                            )
                            .id(message.id)
                        }
                    }
                    .padding()
                }
                .onAppear {
                    scrollToLatest(using: proxy)
                    Task { await session.markVisibleMessagesRead() }
                }
                .onChange(of: session.messages.last?.id) { _, _ in
                    scrollToLatest(using: proxy)
                    Task { await session.markVisibleMessagesRead() }
                }
            }

            Divider()

            VStack(alignment: .leading, spacing: 8) {
                if let errorMessage = viewModel.errorMessage {
                    Label(errorMessage, systemImage: "exclamationmark.triangle.fill")
                        .font(.caption)
                        .foregroundStyle(.red)
                }

                HStack(alignment: .center, spacing: 8) {
                    Button {
                        chooseFile()
                    } label: {
                        Image(systemName: "paperclip")
                    }
                    .help("Choose a file")
                    .disabled(viewModel.isSending || viewModel.isRecording)

                    TextField("Message", text: $viewModel.draft)
                        .textFieldStyle(.roundedBorder)
                        .onSubmit {
                            Task {
                                await viewModel.sendText()
                            }
                        }

                    Image(systemName: viewModel.isRecording ? "mic.fill" : "mic")
                        .foregroundStyle(viewModel.isRecording ? .red : .primary)
                        .frame(width: 28, height: 28)
                        .contentShape(Circle())
                        .gesture(
                            DragGesture(minimumDistance: 0)
                                .onChanged { _ in
                                    viewModel.startRecording()
                                }
                                .onEnded { _ in
                                    viewModel.stopRecordingAndSend()
                                }
                        )
                        .help("Hold to record audio")

                    Button("Send") {
                        Task {
                            await viewModel.sendText()
                        }
                    }
                    .buttonStyle(.borderedProminent)
                    .disabled(
                        viewModel.isSending ||
                        viewModel.draft.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
                    )
                }
            }
            .padding()
        }
    }

    private func chooseFile() {
        let panel = NSOpenPanel()
        panel.canChooseDirectories = false
        panel.canChooseFiles = true
        panel.allowsMultipleSelection = false

        guard panel.runModal() == .OK, let url = panel.url else {
            return
        }

        Task {
            await viewModel.sendFile(url: url)
        }
    }

    private func scrollToLatest(using proxy: ScrollViewProxy) {
        guard let latestID = session.messages.last?.id else {
            return
        }

        withAnimation {
            proxy.scrollTo(latestID, anchor: .bottom)
        }
    }
}
