import SwiftUI

struct ChatView: View {
    @State private var conversation: Conversation
    var appState: AppState
    var conversationListVM: ConversationListVM?

    init(conversation: Conversation, appState: AppState, conversationListVM: ConversationListVM? = nil) {
        self._conversation = State(initialValue: conversation)
        self.appState = appState
        self.conversationListVM = conversationListVM
    }
    @State private var viewModel = ChatViewModel()
    @State private var inputText = ""
    @State private var replyTo: Message?
    @State private var showGroupInfo = false
    @State private var showDMInfo = false
    @State private var showSearch = false
    @State private var showDeleteConfirm = false
    @State private var showError = false
    @State private var memberListenerTask: Task<Void, Never>?
    @State private var forwardingMessage: Message?
    @State private var showForwardPicker = false
    @State private var showPinnedMessages = false
    @State private var scrollTarget: String?
    @State private var showVerification = false
    @State private var verificationStatus: String = "unverified"

    private var currentUserId: String {
        appState.currentUser?.id ?? ""
    }

    private var isPartnerOnline: Bool {
        guard !conversation.isGroup,
              let partnerId = conversation.dmPartnerId(currentUserId: currentUserId),
              let listVM = conversationListVM else {
            return false
        }
        return listVM.onlineUsers.contains(partnerId)
    }

    var body: some View {
        VStack(spacing: 0) {
            searchBar
            messagesScrollView
            replyPreview
            inputView
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbar { toolbarContent }
        .alert("Delete Conversation?", isPresented: $showDeleteConfirm) {
            Button("Cancel", role: .cancel) {}
            Button("Delete", role: .destructive) {
                Task { await appState.chatClient.deleteConversation(convId: conversation.id) }
            }
        } message: {
            Text(conversation.isGroup
                 ? "This will remove all members and delete the conversation."
                 : "This will remove you from the conversation.")
        }
        .alert("Error", isPresented: $showError) {
            Button("OK", role: .cancel) {}
        } message: {
            Text(viewModel.errorMessage ?? "Unknown error")
        }
        .sheet(isPresented: $showGroupInfo) {
            GroupInfoView(conversation: $conversation, appState: appState, conversationListVM: conversationListVM)
        }
        .sheet(isPresented: $showDMInfo) {
            if let partnerId = conversation.dmPartnerId(currentUserId: currentUserId) {
                ProfileView(appState: appState, isOwnProfile: false, userId: partnerId)
            }
        }
        .sheet(isPresented: $showForwardPicker) {
            if let msg = forwardingMessage {
                ForwardPickerView(message: msg, appState: appState)
            }
        }
        .sheet(isPresented: $showVerification) {
            if let partnerId = conversation.dmPartnerId(currentUserId: currentUserId) {
                NavigationStack {
                    SafetyNumberView(
                        peerUserId: partnerId,
                        peerUsername: conversation.displayName(currentUserId: currentUserId),
                        chatClient: appState.chatClient
                    )
                    .toolbar {
                        ToolbarItem(placement: .topBarLeading) {
                            Button("Done") { showVerification = false }
                        }
                    }
                }
            }
        }
        .sheet(isPresented: $showPinnedMessages) {
            PinnedMessagesView(
                messages: viewModel.messages.filter { $0.pinnedAt != nil },
                onScrollTo: { scrollTarget = $0 }
            )
        }
        .task {
            // Use already-loaded data from conversation list (avoid redundant list_conversations call)
            if let updated = conversationListVM?.conversations.first(where: { $0.id == conversation.id }) {
                conversation = updated
            }
            conversationListVM?.markConversationRead(convId: conversation.id)
            await viewModel.loadMessages(convId: conversation.id, chatClient: appState.chatClient)
            viewModel.startNotificationListener(convId: conversation.id, chatClient: appState.chatClient)

            // Load verification status for DM partner
            if !conversation.isGroup,
               let partnerId = conversation.dmPartnerId(currentUserId: currentUserId) {
                verificationStatus = await appState.chatClient.getVerificationStatus(userId: partnerId)
            }

            memberListenerTask = Task {
                for await notification in await appState.chatClient.makeNotificationStream() {
                    switch notification {
                    case .memberAdded, .memberRemoved, .conversationRenamed:
                        let refreshed = await appState.chatClient.listConversations()
                        if let updated = refreshed.first(where: { $0.id == conversation.id }) {
                            await MainActor.run { conversation = updated }
                        }
                    default:
                        break
                    }
                }
            }
        }
        .onDisappear {
            viewModel.stop()
            memberListenerTask?.cancel()
            memberListenerTask = nil
        }
    }

    // MARK: - Search Bar

    @ViewBuilder
    private var searchBar: some View {
        if showSearch {
            SearchOverlayView(
                query: $viewModel.searchQuery,
                matchCount: viewModel.searchResults.count,
                currentIndex: viewModel.currentSearchIndex,
                onSearch: { viewModel.search(query: $0) },
                onNext: { viewModel.nextSearchResult() },
                onPrev: { viewModel.prevSearchResult() },
                onClose: { showSearch = false; viewModel.search(query: "") }
            )
        }
    }

    // MARK: - Messages

    private var messagesScrollView: some View {
        ScrollViewReader { proxy in
            ScrollView {
                LazyVStack(spacing: 8) {
                    if viewModel.messages.count >= 50 {
                        Button("Load older messages") {
                            Task {
                                await viewModel.loadOlderMessages(convId: conversation.id, chatClient: appState.chatClient)
                            }
                        }
                        .font(.caption)
                        .padding()
                    }

                    ForEach(viewModel.messages) { message in
                        messageBubble(for: message)
                            .id(message.id)
                    }
                }
                .padding(.horizontal)
                .padding(.vertical, 8)
            }
            .onChange(of: viewModel.messages.count) {
                if let lastId = viewModel.messages.last?.id {
                    withAnimation { proxy.scrollTo(lastId, anchor: .bottom) }
                }
            }
            .onChange(of: scrollTarget) {
                if let target = scrollTarget {
                    withAnimation { proxy.scrollTo(target, anchor: .center) }
                    scrollTarget = nil
                }
            }
        }
    }

    private func messageBubble(for message: Message) -> some View {
        let isCurrentSearch = viewModel.searchResults.indices.contains(viewModel.currentSearchIndex)
            && viewModel.searchResults[viewModel.currentSearchIndex] == message.id
        return MessageBubbleView(
            message: message,
            isMine: message.isMine(currentUserId: currentUserId),
            isGroup: conversation.isGroup,
            isHighlighted: viewModel.searchResults.contains(message.id),
            isCurrentSearchResult: isCurrentSearch,
            chatClient: appState.chatClient,
            currentUserId: currentUserId,
            onReply: { replyTo = message },
            onReact: { reaction in
                Task {
                    await viewModel.reactToMessage(
                        messageId: message.id, convId: conversation.id,
                        reaction: reaction, currentUserId: currentUserId,
                        chatClient: appState.chatClient
                    )
                }
            },
            onForward: {
                forwardingMessage = message
                showForwardPicker = true
            },
            onPin: { pin in
                Task {
                    await viewModel.pinMessage(
                        messageId: message.id, convId: conversation.id,
                        pin: pin, chatClient: appState.chatClient
                    )
                }
            },
            onDelete: {
                Task {
                    await viewModel.deleteMessage(
                        messageId: message.id, convId: conversation.id,
                        chatClient: appState.chatClient
                    )
                }
            }
        )
    }

    // MARK: - Reply Preview

    @ViewBuilder
    private var replyPreview: some View {
        if let reply = replyTo {
            HStack {
                Rectangle()
                    .fill(.blue)
                    .frame(width: 3)
                VStack(alignment: .leading) {
                    Text(reply.senderUsername)
                        .font(.caption.bold())
                    Text(reply.text ?? "")
                        .font(.caption)
                        .lineLimit(1)
                }
                Spacer()
                Button(action: { replyTo = nil }) {
                    Image(systemName: "xmark.circle.fill")
                        .foregroundStyle(.secondary)
                }
            }
            .padding(.horizontal)
            .padding(.vertical, 6)
            .background(.ultraThinMaterial)
        }
    }

    // MARK: - Input

    private var inputView: some View {
        MessageInputView(
            text: $inputText,
            isSending: viewModel.isSending,
            onSend: {
                Task {
                    let text = inputText
                    inputText = ""
                    let reply = replyTo?.id
                    replyTo = nil
                    await viewModel.sendMessage(
                        convId: conversation.id, text: text,
                        members: conversation.members,
                        chatClient: appState.chatClient, replyTo: reply
                    )
                }
            },
            onImageSelected: { imageData in
                Task {
                    viewModel.isSending = true
                    let (success, msg, sentMessage) = await appState.chatClient.sendImage(
                        convId: conversation.id, imageData: imageData,
                        members: conversation.members
                    )
                    viewModel.isSending = false
                    if success, let sentMessage {
                        if !viewModel.messages.contains(where: { $0.id == sentMessage.id }) {
                            viewModel.messages.append(sentMessage)
                        }
                        await viewModel.saveCache(convId: conversation.id, chatClient: appState.chatClient)
                    } else if !success {
                        viewModel.errorMessage = msg
                        showError = true
                    }
                }
            },
            onFileSelected: { fileData, filename, mimeType in
                Task {
                    viewModel.isSending = true
                    let (success, msg, sentMessage) = await appState.chatClient.sendFile(
                        convId: conversation.id, fileData: fileData,
                        filename: filename, mimeType: mimeType,
                        members: conversation.members
                    )
                    viewModel.isSending = false
                    if success, let sentMessage {
                        if !viewModel.messages.contains(where: { $0.id == sentMessage.id }) {
                            viewModel.messages.append(sentMessage)
                        }
                        await viewModel.saveCache(convId: conversation.id, chatClient: appState.chatClient)
                    } else if !success {
                        viewModel.errorMessage = msg
                        showError = true
                    }
                }
            },
            members: conversation.members
        )
    }

    // MARK: - Toolbar

    @ToolbarContentBuilder
    private var toolbarContent: some ToolbarContent {
        ToolbarItem(placement: .principal) {
            HStack(spacing: 8) {
                CircularAvatarView(
                    name: conversation.displayName(currentUserId: currentUserId),
                    imageData: conversationListVM?.avatarCache[conversation.id],
                    size: 28,
                    isGroup: conversation.isGroup
                )
                Text(conversation.displayName(currentUserId: currentUserId))
                    .font(.headline)
                if !conversation.isGroup && verificationStatus == "verified" {
                    Image(systemName: "checkmark.shield.fill")
                        .font(.caption)
                        .foregroundStyle(.green)
                }
                if isPartnerOnline {
                    Circle().fill(.green).frame(width: 8, height: 8)
                }
            }
        }

        ToolbarItem(placement: .topBarTrailing) {
            HStack(spacing: 16) {
                if !conversation.isGroup {
                    Button(action: { showVerification = true }) {
                        Image(systemName: verificationStatus == "verified" ? "checkmark.shield.fill" : "shield")
                            .foregroundStyle(verificationStatus == "verified" ? .green : .secondary)
                    }
                }
                Button(action: { showPinnedMessages = true }) {
                    Image(systemName: "pin")
                }
                Button(action: { showSearch.toggle() }) {
                    Image(systemName: "magnifyingglass")
                }
                if conversation.isGroup {
                    Button(action: { showGroupInfo = true }) {
                        Image(systemName: "info.circle")
                    }
                } else {
                    Button(action: { showDMInfo = true }) {
                        Image(systemName: "info.circle")
                    }
                }
                if !conversation.isGroup || conversation.createdBy == currentUserId {
                    Button(action: { showDeleteConfirm = true }) {
                        Image(systemName: "trash").foregroundStyle(.red)
                    }
                }
            }
        }
    }
}
