import ForgejoKit
import SwiftUI

struct MentionableEditorField: View {
    @Binding var text: String
    @Binding var selectedTab: EditPreviewTab
    var users: [User]
    var minHeight: CGFloat = 150
    var showToolbar: Bool = false
    var onUploadImage: ((Data, String, String) async throws -> String)?

    @State private var mentionQuery: String?

    private var matchingUsers: [User] {
        guard let query = mentionQuery, !query.isEmpty else {
            return []
        }
        return users.filter { $0.login.localizedCaseInsensitiveContains(query) }
    }

    var body: some View {
        VStack(spacing: 0) {
            MarkdownEditorField(
                text: $text,
                selectedTab: $selectedTab,
                minHeight: minHeight,
                showToolbar: showToolbar,
                onUploadImage: onUploadImage,
            )

            if selectedTab == .edit, mentionQuery != nil, !matchingUsers.isEmpty {
                ScrollView(.horizontal, showsIndicators: false) {
                    HStack(spacing: 6) {
                        ForEach(matchingUsers.prefix(10)) { user in
                            Button {
                                insertMention(user.login)
                            } label: {
                                Text("@\(user.login)")
                                    .font(.caption)
                                    .padding(.horizontal, 8)
                                    .padding(.vertical, 4)
                                    .glassEffect(.regular)
                            }
                            .buttonStyle(.plain)
                        }
                    }
                    .padding(.horizontal, 4)
                    .padding(.vertical, 6)
                }
            }
        }
        .onChange(of: text) {
            mentionQuery = detectMentionQuery(in: text)
        }
    }

    private func detectMentionQuery(in text: String) -> String? {
        // Find the last @ that isn't preceded by a word character
        guard let atIndex = text.lastIndex(of: "@") else { return nil }

        // Check that there's no space between @ and cursor (end of string)
        let afterAt = text[text.index(after: atIndex)...]
        guard !afterAt.contains(" "), !afterAt.contains("\n") else { return nil }

        // Check that @ is at start or preceded by whitespace/newline
        if atIndex != text.startIndex {
            let before = text[text.index(before: atIndex)]
            guard before == " " || before == "\n" || before == "\t" else { return nil }
        }

        return String(afterAt)
    }

    private func insertMention(_ username: String) {
        guard let atIndex = text.lastIndex(of: "@") else { return }
        text = String(text[..<atIndex]) + "@\(username) "
        mentionQuery = nil
    }
}

#if DEBUG
    #Preview {
        @Previewable @State var text = "Hello @"
        @Previewable @State var tab: EditPreviewTab = .edit
        MentionableEditorField(
            text: $text,
            selectedTab: $tab,
            users: [.preview, .previewBot],
        )
        .padding()
    }
#endif
