//
//  ChatsTab.swift
//  VolnahubApp
//
//  Created by cheykrym on 09/06/2025.
//

import SwiftUI
#if canImport(UIKit)
import UIKit
#endif

struct ChatsTab: View {
    var currentUserId: String?
    @Binding var searchRevealProgress: CGFloat
    @Binding var searchText: String
    private let searchService = SearchService()
    @StateObject private var viewModel = PrivateChatsViewModel()
    @State private var selectedChatId: String?
    @State private var searchDragStartProgress: CGFloat = 0
    @State private var isSearchGestureActive: Bool = false
    @State private var globalSearchResults: [UserSearchResult] = []
    @State private var isGlobalSearchLoading: Bool = false
    @State private var globalSearchError: String?
    @State private var globalSearchTask: Task<Void, Never>? = nil

    private let searchRevealDistance: CGFloat = 90

    init(currentUserId: String? = nil, searchRevealProgress: Binding<CGFloat>, searchText: Binding<String>) {
        self.currentUserId = currentUserId
        self._searchRevealProgress = searchRevealProgress
        self._searchText = searchText
    }

    var body: some View {
        content
            .background(Color(UIColor.systemBackground))
            .onAppear {
                viewModel.loadInitialChats()
                handleSearchQueryChange(searchText)
            }
            .onReceive(NotificationCenter.default.publisher(for: .debugRefreshChats)) { _ in
                viewModel.refresh()
            }
            .onChange(of: searchText) { newValue in
                handleSearchQueryChange(newValue)
            }
            .onDisappear {
                globalSearchTask?.cancel()
                globalSearchTask = nil
            }
    }

    @ViewBuilder
    private var content: some View {
        if viewModel.isInitialLoading && viewModel.chats.isEmpty {
            loadingState
        } else if let message = viewModel.errorMessage, viewModel.chats.isEmpty {
            errorState(message: message)
        } else if viewModel.chats.isEmpty {
            emptyState
        } else {
            chatList
        }
    }

    private var chatList: some View {
        List {
//            VStack(spacing: 0) {
//                searchBar
//                    .padding(.horizontal, 16)
//                    .padding(.vertical, 8)
//            }
//            .background(Color(UIColor.systemBackground))

            if let message = viewModel.errorMessage {
                Section {
                    HStack(alignment: .top, spacing: 8) {
                        Image(systemName: "exclamationmark.triangle.fill")
                            .foregroundColor(.orange)
                        Text(message)
                            .font(.subheadline)
                            .foregroundColor(.orange)
                        Spacer(minLength: 0)
                        Button(action: { viewModel.refresh() }) {
                            Text(NSLocalizedString("Обновить", comment: ""))
                                .font(.subheadline)
                        }
                    }
                    .padding(.vertical, 4)
                }
                .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
            }

            if isSearching {
                Section(header: localSearchHeader) {
                    if localSearchResults.isEmpty {
                        emptySearchResultView
                            .listRowInsets(EdgeInsets(top: 24, leading: 16, bottom: 24, trailing: 16))
                            .listRowSeparator(.hidden)
                    } else {
                        ForEach(localSearchResults) { chat in
                            chatRowItem(for: chat)
                        }
                    }
                }

                Section(header: globalSearchHeader) {
                    globalSearchContent
                }
            } else {
                ForEach(viewModel.chats) { chat in
                    chatRowItem(for: chat)
                }

                if viewModel.isLoadingMore {
                    loadingMoreRow
                }
            }
        }
        .listStyle(.plain)
        .modifier(ScrollDismissesKeyboardModifier())
        .simultaneousGesture(searchBarGesture)
        .simultaneousGesture(tapToDismissKeyboardGesture)
//        .safeAreaInset(edge: .top) {
//            VStack(spacing: 0) {
//                searchBar
//                    .padding(.horizontal, 16)
//                    .padding(.top, 8)
//                    .padding(.bottom, 8)
//                Divider()
//            }
//            .background(Color(UIColor.systemBackground))
//        }
    }

    private var searchBarGesture: some Gesture {
        DragGesture(minimumDistance: 10, coordinateSpace: .local)
            .onChanged { value in
                let verticalTranslation = value.translation.height
                let horizontalTranslation = value.translation.width

                if !isSearchGestureActive {
                    guard abs(verticalTranslation) > abs(horizontalTranslation) else { return }
                    if searchRevealProgress <= 0.001 && verticalTranslation < 0 { return }
                    isSearchGestureActive = true
                    searchDragStartProgress = searchRevealProgress
                }

                guard isSearchGestureActive else { return }

                let delta = verticalTranslation / searchRevealDistance
                let newProgress = searchDragStartProgress + delta
                searchRevealProgress = max(0, min(1, newProgress))
            }
            .onEnded { _ in
                guard isSearchGestureActive else { return }
                isSearchGestureActive = false

                let target: CGFloat = searchRevealProgress > 0.5 ? 1 : 0
                withAnimation(.spring(response: 0.35, dampingFraction: 0.75)) {
                    searchRevealProgress = target
                }
            }
    }

    private var tapToDismissKeyboardGesture: some Gesture {
        TapGesture().onEnded {
            dismissKeyboard()
        }
    }

    private var isSearching: Bool {
        !searchText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }

    private var filteredChats: [PrivateChatListItem] {
        let trimmedQuery = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmedQuery.isEmpty else { return viewModel.chats }
        let lowercasedQuery = trimmedQuery.lowercased()
        return viewModel.chats.filter { chat in
            let searchableValues = [
                chat.chatData?.customName,
                chat.chatData?.fullName,
                chat.chatData?.login,
                chat.lastMessage?.content
            ]
            return searchableValues
                .compactMap { $0?.lowercased() }
                .contains(where: { $0.contains(lowercasedQuery) })
        }
    }

    private var localSearchResults: [PrivateChatListItem] {
        Array(filteredChats.prefix(5))
    }

    private var localSearchHeader: some View {
        Text(NSLocalizedString("Локальные чаты", comment: "Local search section"))
    }

    private var globalSearchHeader: some View {
        Text(NSLocalizedString("Глобальный поиск", comment: "Global search section"))
    }

    @ViewBuilder
    private var globalSearchContent: some View {
        if isGlobalSearchLoading {
            globalSearchLoadingRow
        } else if let error = globalSearchError {
            globalSearchErrorRow(message: error)
        } else if globalSearchResults.isEmpty {
            globalSearchEmptyRow
        } else {
            ForEach(globalSearchResults) { user in
                globalSearchRow(for: user)
            }
        }
    }

    private var emptySearchResultView: some View {
        VStack(spacing: 8) {
            Image(systemName: "text.magnifyingglass")
                .font(.system(size: 40))
                .foregroundColor(.secondary)
            Text(NSLocalizedString("Ничего не найдено", comment: ""))
                .font(.headline)
            Text(NSLocalizedString("Попробуйте изменить запрос поиска.", comment: ""))
                .font(.subheadline)
                .foregroundColor(.secondary)
                .multilineTextAlignment(.center)
        }
        .frame(maxWidth: .infinity)
    }

    private var loadingState: some View {
        VStack(spacing: 12) {
            ProgressView()
            Text(NSLocalizedString("Загружаем чаты…", comment: ""))
                .font(.subheadline)
                .foregroundColor(.secondary)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

    private func errorState(message: String) -> some View {
        VStack(spacing: 12) {
            Image(systemName: "exclamationmark.bubble")
                .font(.system(size: 48))
                .foregroundColor(.orange)
            Text(message)
                .font(.body)
                .multilineTextAlignment(.center)
                .foregroundColor(.primary)
            Button(action: { viewModel.loadInitialChats(force: true) }) {
                Text(NSLocalizedString("Повторить", comment: ""))
                    .font(.headline)
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

    private var emptyState: some View {
        VStack(spacing: 12) {
            Image(systemName: "bubble.left")
                .font(.system(size: 48))
                .foregroundColor(.secondary)
            Text(NSLocalizedString("Пока что у вас нет чатов", comment: ""))
                .font(.body)
                .foregroundColor(.secondary)
            Button(action: { viewModel.refresh() }) {
                Text(NSLocalizedString("Обновить", comment: ""))
            }
            .buttonStyle(.bordered)
        }
        .padding()
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

    private var loadingMoreRow: some View {
        HStack {
            Spacer()
            ProgressView()
                .padding(.vertical, 12)
            Spacer()
        }
        .listRowSeparator(.hidden)
    }

    @ViewBuilder
    private func chatRowItem(for chat: PrivateChatListItem) -> some View {
        Button {
            selectedChatId = chat.chatId
        } label: {
            ChatRowView(chat: chat, currentUserId: currentUserId)
                .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
        .contextMenu {
            Button(action: {}) {
                Label(NSLocalizedString("Закрепить (скоро)", comment: ""), systemImage: "pin")
            }

            Button(action: {}) {
                Label(NSLocalizedString("Без звука (скоро)", comment: ""), systemImage: "speaker.slash")
            }

            Button(role: .destructive, action: {}) {
                Label(NSLocalizedString("Удалить чат (скоро)", comment: ""), systemImage: "trash")
            }
        }
        .background(
            NavigationLink(
                destination: ChatPlaceholderView(chat: chat),
                tag: chat.chatId,
                selection: $selectedChatId
            ) {
                EmptyView()
            }
            .hidden()
        )
        .onAppear {
            guard !isSearching else { return }
            viewModel.loadMoreIfNeeded(currentItem: chat)
        }
    }

    private var globalSearchLoadingRow: some View {
        HStack {
            ProgressView()
                .progressViewStyle(CircularProgressViewStyle())
            Text(NSLocalizedString("Ищем пользователей…", comment: "Global search loading"))
                .font(.footnote)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(.vertical, 12)
        .listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16))
        .listRowSeparator(.hidden)
    }

    private func globalSearchErrorRow(message: String) -> some View {
        Text(message)
            .font(.footnote)
            .foregroundColor(.orange)
            .padding(.vertical, 12)
            .frame(maxWidth: .infinity, alignment: .leading)
            .listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16))
            .listRowSeparator(.hidden)
    }

    private var globalSearchEmptyRow: some View {
        Text(NSLocalizedString("Ничего не найдено", comment: "Global search empty state"))
            .font(.footnote)
            .foregroundColor(.secondary)
            .padding(.vertical, 12)
            .frame(maxWidth: .infinity, alignment: .leading)
            .listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16))
            .listRowSeparator(.hidden)
    }

    private func globalSearchRow(for user: UserSearchResult) -> some View {
        HStack(spacing: 12) {
            Circle()
                .fill(user.isOfficial ? Color.accentColor.opacity(0.85) : Color.accentColor.opacity(0.15))
                .frame(width: 44, height: 44)
                .overlay(
                    Text(user.avatarInitial)
                        .font(.headline)
                        .foregroundColor(user.isOfficial ? .white : Color.accentColor)
                )

            VStack(alignment: .leading, spacing: 4) {
                HStack(spacing: 6) {
                    Text(user.displayName)
                        .fontWeight(user.isOfficial ? .semibold : .regular)
                        .foregroundColor(.primary)
                        .lineLimit(1)
                        .truncationMode(.tail)

                    if user.isOfficial {
                        Image(systemName: "checkmark.seal.fill")
                            .foregroundColor(Color.accentColor)
                            .font(.caption)
                    }
                }

                if let secondary = user.secondaryLabelForSearch {
                    Text(secondary)
                        .font(.footnote)
                        .foregroundColor(.secondary)
                        .lineLimit(1)
                        .truncationMode(.tail)
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
        }
        .padding(.vertical, 8)
        .listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
    }
}

private extension ChatsTab {
    func dismissKeyboard() {
#if canImport(UIKit)
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
#endif
    }

    func handleSearchQueryChange(_ query: String) {
        let trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines)

        if trimmed.isEmpty {
            resetGlobalSearch()
            return
        }

        globalSearchTask?.cancel()
        globalSearchTask = nil

        guard trimmed.count >= 2 else {
            globalSearchResults = []
            globalSearchError = nil
            isGlobalSearchLoading = false
            return
        }

        isGlobalSearchLoading = true
        globalSearchError = nil

        globalSearchTask = Task {
            try? await Task.sleep(nanoseconds: 300_000_000)
            guard !Task.isCancelled else { return }

            do {
                let data = try await searchService.search(query: trimmed)
                guard !Task.isCancelled else { return }
                await MainActor.run {
                    globalSearchResults = data.users
                    isGlobalSearchLoading = false
                    globalSearchError = nil
                    globalSearchTask = nil
                }
            } catch is CancellationError {
                // Ignore cancellation
            } catch {
                guard !Task.isCancelled else { return }
                await MainActor.run {
                    globalSearchResults = []
                    isGlobalSearchLoading = false
                    globalSearchError = friendlyErrorMessage(for: error)
                    globalSearchTask = nil
                }
            }
        }
    }

    func resetGlobalSearch() {
        globalSearchTask?.cancel()
        globalSearchTask = nil
        globalSearchResults = []
        globalSearchError = nil
        isGlobalSearchLoading = false
    }

    func friendlyErrorMessage(for error: Error) -> String {
        if let searchError = error as? SearchServiceError {
            return searchError.errorDescription ?? NSLocalizedString("Не удалось выполнить поиск.", comment: "Search error fallback")
        }

        if let networkError = error as? NetworkError {
            switch networkError {
            case .unauthorized:
                return NSLocalizedString("Сессия истекла. Войдите снова.", comment: "Search error unauthorized")
            case .invalidURL, .noResponse:
                return NSLocalizedString("Ошибка соединения с сервером.", comment: "Search error connection")
            case .network(let underlying):
                return underlying.localizedDescription
            case .server(let statusCode, _):
                return String(format: NSLocalizedString("Сервер вернул ошибку (%d).", comment: "Search error server status"), statusCode)
            }
        }

        if (error as NSError).code == NSURLErrorCancelled { // доп. подстраховка
            return NSLocalizedString("Поиск отменён.", comment: "Search cancelled")
        }

        return NSLocalizedString("Произошла неизвестная ошибка.", comment: "Search unknown error")
    }
}

private struct ScrollDismissesKeyboardModifier: ViewModifier {
    func body(content: Content) -> some View {
        if #available(iOS 16.0, *) {
            content.scrollDismissesKeyboard(.interactively)
        } else {
            content
        }
    }
}

private struct ChatRowView: View {
    let chat: PrivateChatListItem
    let currentUserId: String?

    private var title: String {
        switch chat.chatType {
        case .self:
            return NSLocalizedString("Избранные сообщения", comment: "")
        case .privateChat, .unknown:
            if let custom = chat.chatData?.customName, !custom.isEmpty {
                return custom
            }
            if let full = chat.chatData?.fullName, !full.isEmpty {
                return full
            }
            if let login = chat.chatData?.login, !login.isEmpty {
                return "@\(login)"
            }
            return NSLocalizedString("Неизвестный пользователь", comment: "")
        }
    }

    private var officialFullName: String? {
        guard let name = chat.chatData?.fullName?.trimmingCharacters(in: .whitespacesAndNewlines), !name.isEmpty else {
            return nil
        }
        return NSLocalizedString(name, comment: "")
    }

    private var loginDisplay: String? {
        guard let login = chat.chatData?.login?.trimmingCharacters(in: .whitespacesAndNewlines), !login.isEmpty else {
            return nil
        }
        return "@\(login)"
    }

    private var isOfficial: Bool {
        officialFullName != nil
    }

    private var avatarBackgroundColor: Color {
        isOfficial ? Color.accentColor.opacity(0.85) : Color.accentColor.opacity(0.15)
    }

    private var avatarTextColor: Color {
        isOfficial ? Color.white : Color.accentColor
    }

    private var messagePreview: String {
        guard let message = chat.lastMessage else {
            return NSLocalizedString("Нет сообщений", comment: "")
        }

        let body = messageBody(for: message)
        guard let prefix = authorPrefix(for: message) else {
            return body
        }
        return body.isEmpty ? prefix : "\(body)"
//        return body.isEmpty ? prefix : "\(prefix): \(body)"
    }

    private func messageBody(for message: MessageItem) -> String {
        if let content = trimmed(message.content), !content.isEmpty {
            return content
        }

        if message.mediaLink != nil {
            return NSLocalizedString("Вложение", comment: "")
        }

        return NSLocalizedString("Сообщение", comment: "")
    }

    private func authorPrefix(for message: MessageItem) -> String? {
        let isCurrentUser = currentUserId.map { $0 == message.senderId } ?? false
        if isCurrentUser {
            return NSLocalizedString("Вы", comment: "")
        }

        let profile = message.senderData ?? chat.chatData
        return displayName(for: profile)
    }

    private func displayName(for profile: ChatProfile?) -> String? {
        guard let profile else { return nil }

        let login = trimmed(profile.login)
        let customName = trimmed(profile.customName)
        let fullName = trimmed(profile.fullName)
        let isOfficialProfile = fullName != nil

        if isOfficialProfile, let login {
            if let customName {
                return "@\(login) (\(customName))"
            }
            return "@\(login)"
        }

        if let customName {
            return customName
        }

        if let login {
            return "@\(login)"
        }

        return fullName
    }

    private func trimmed(_ string: String?) -> String? {
        guard let string = string?.trimmingCharacters(in: .whitespacesAndNewlines), !string.isEmpty else {
            return nil
        }
        return string
    }

    private var timestamp: String? {
        let date = chat.lastMessage?.createdAt ?? chat.createdAt
        guard let date else { return nil }
        return ChatRowView.formattedTimestamp(for: date)
    }

    private var initial: String {
        let sourceName: String

        if let full = officialFullName {
            sourceName = full
        } else if let custom = chat.chatData?.customName, !custom.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
            sourceName = custom
        } else if let login = chat.chatData?.login?.trimmingCharacters(in: .whitespacesAndNewlines), !login.isEmpty {
            sourceName = login
        } else {
            sourceName = NSLocalizedString("Неизвестный пользователь", comment: "")
        }

        if let character = sourceName.first(where: { !$0.isWhitespace && $0 != "@" }) {
            return String(character).uppercased()
        }

        return "?"
    }

    private var subtitleColor: Color {
        chat.unreadCount > 0 ? .primary : .secondary
    }

    private var shouldShowReadStatus: Bool {
        guard let message = chat.lastMessage else { return false }
        let isCurrentUser = currentUserId.map { $0 == message.senderId } ?? false
        return isCurrentUser
    }

    private var readStatusIconName: String {
        guard let message = chat.lastMessage else { return "" }
        return message.isViewed == true ? "checkmark.circle.fill" : "checkmark.circle"
    }

    private var readStatusColor: Color {
        guard let message = chat.lastMessage else { return .secondary }
        return message.isViewed == true ? Color.accentColor : Color.secondary
    }

    var body: some View {
        HStack(spacing: 12) {
            Circle()
                .fill(avatarBackgroundColor)
                .frame(width: 44, height: 44)
                .overlay(
                    Text(initial)
                        .font(.headline)
                        .foregroundColor(avatarTextColor)
                )

            VStack(alignment: .leading, spacing: 4) {
                if let officialName = officialFullName {
                    HStack(spacing: 6) {
                        Text(officialName)
                            .fontWeight(.semibold)
                            .foregroundColor(.primary)
                            .lineLimit(1)
                            .truncationMode(.tail)

                        Image(systemName: "checkmark.seal.fill")
                            .foregroundColor(Color.accentColor)
                            .font(.caption)
                    }

//                    if let login = loginDisplay {
//                        Text(login)
//                            .font(.footnote)
//                            .foregroundColor(.secondary)
//                            .lineLimit(1)
//                            .truncationMode(.tail)
//                    }
                } else {
                    Text(title)
                        .fontWeight(chat.unreadCount > 0 ? .semibold : .regular)
                        .foregroundColor(.primary)
                        .lineLimit(1)
                        .truncationMode(.tail)
                }

                Text(messagePreview)
                    .font(.subheadline)
                    .foregroundColor(subtitleColor)
                    .lineLimit(2)
                    .truncationMode(.tail)
            }
            .frame(maxWidth: .infinity, alignment: .leading)

            Spacer()

            VStack(alignment: .trailing, spacing: 6) {
                if let timestamp {
                    HStack(spacing: 4) {
                        if shouldShowReadStatus {
                            Image(systemName: readStatusIconName)
                                .foregroundColor(readStatusColor)
                                .font(.caption2)
                        }

                        Text(timestamp)
                            .font(.caption)
                            .foregroundColor(.secondary)
                    }
                }

                if chat.unreadCount > 0 {
                    Text("\(chat.unreadCount)")
                        .font(.caption2.bold())
                        .foregroundColor(.white)
                        .padding(.horizontal, 8)
                        .padding(.vertical, 4)
                        .background(
                            Capsule().fill(Color.accentColor)
                        )
                }
            }
        }
        .padding(.vertical, 8)
    }

    private static func formattedTimestamp(for date: Date) -> String {
        let calendar = Calendar.current
        let locale = Locale.current

        let now = Date()
        let startOfNow = calendar.startOfDay(for: now)
        let startOfDate = calendar.startOfDay(for: date)
        let diff = calendar.dateComponents([.day], from: startOfDate, to: startOfNow).day ?? 0

        if diff <= 0 {
            return timeString(for: date, locale: locale)
        }

        if diff == 1 {
            return locale.identifier.lowercased().hasPrefix("ru") ? "Вчера" : "Yesterday"
        }

        if diff < 7 {
            return weekdayFormatter(for: locale).string(from: date)
        }

        if diff < 365 {
            return monthDayFormatter(for: locale).string(from: date)
        }

        return fullDateFormatter(for: locale).string(from: date)
    }

    private static func timeString(for date: Date, locale: Locale) -> String {
        let timeFormat = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: locale) ?? ""
        let is12Hour = timeFormat.contains("a") || timeFormat.contains("h") || timeFormat.contains("K")

        let formatter = DateFormatter()
        formatter.locale = locale
        if is12Hour {
            formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "h:mm a", options: 0, locale: locale) ?? "h:mm a"
        } else {
            formatter.dateFormat = "HH:mm"
        }
        return formatter.string(from: date)
    }

    private static func weekdayFormatter(for locale: Locale) -> DateFormatter {
        let formatter = DateFormatter()
        formatter.locale = locale
        formatter.setLocalizedDateFormatFromTemplate("EEE")
        return formatter
    }

    private static func monthDayFormatter(for locale: Locale) -> DateFormatter {
        let formatter = DateFormatter()
        formatter.locale = locale
        formatter.setLocalizedDateFormatFromTemplate("MMM d")
        return formatter
    }

    private static func fullDateFormatter(for locale: Locale) -> DateFormatter {
        let formatter = DateFormatter()
        formatter.locale = locale
        formatter.dateFormat = "dd.MM.yy"
        return formatter
    }
}

struct ChatsTab_Previews: PreviewProvider {
    struct Wrapper: View {
        @State private var progress: CGFloat = 1
        @State private var searchText: String = ""

        var body: some View {
            ChatsTab(searchRevealProgress: $progress, searchText: $searchText)
                .environmentObject(ThemeManager())
        }
    }

    static var previews: some View {
        Wrapper()
    }
}

private struct ChatPlaceholderView: View {
    let chat: PrivateChatListItem

    private var companionId: String {
        if let profileId = chat.chatData?.userId {
            return profileId
        }
        if let senderId = chat.lastMessage?.senderId {
            return senderId
        }
        return NSLocalizedString("Неизвестный", comment: "")
    }

    var body: some View {
        VStack(spacing: 16) {
            Text(NSLocalizedString("Экран чата в разработке", comment: ""))
                .font(.headline)

            VStack(alignment: .leading, spacing: 8) {
                HStack {
                    Text("Chat ID:")
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                    Text(chat.chatId)
                        .font(.body.monospaced())
                }

                if companionId != NSLocalizedString("Неизвестный", comment: "") {
                    HStack {
                        Text("Companion ID:")
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                        Text(companionId)
                            .font(.body.monospaced())
                    }
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)

            Spacer()
        }
        .padding()
        .navigationTitle(title)
        .navigationBarTitleDisplayMode(.inline)
    }

    private var title: String {
        if let full = chat.chatData?.fullName, !full.isEmpty {
            return full
        }
        if let custom = chat.chatData?.customName, !custom.isEmpty {
            return custom
        }
        if let login = chat.chatData?.login, !login.isEmpty {
            return "@\(login)"
        }
        return NSLocalizedString("Чат", comment: "")
    }
}

extension Notification.Name {
    static let debugRefreshChats = Notification.Name("debugRefreshChats")
}
