import SwiftUI

// MARK: - Chat List Search Content

/// Search overlay for ChatListView — shows recent searches or search results.
/// Matches Android's three-state pattern: skeleton → empty → results.
struct ChatListSearchContent: View {
    let searchText: String
    @ObservedObject var viewModel: ChatListViewModel
    var onSelectRecent: (String) -> Void
    var onOpenDialog: (ChatRoute) -> Void

    var body: some View {
        let trimmed = searchText.trimmingCharacters(in: .whitespaces)
        if trimmed.isEmpty {
            recentSearchesSection
        } else {
            activeSearchContent
        }
    }
}

// MARK: - Active Search (Three States)

private extension ChatListSearchContent {
    /// Desktop-parity: skeleton ↔ empty ↔ results — only one visible at a time.
    /// Uses unified search policy from ChatListViewModel callback merge.
    @ViewBuilder
    var activeSearchContent: some View {
        let hasAnyResult = !viewModel.serverSearchResults.isEmpty

        if viewModel.isServerSearching && !hasAnyResult {
            SearchSkeletonView()
        } else if !viewModel.isServerSearching && !hasAnyResult {
            noResultsState
        } else {
            resultsList(results: viewModel.serverSearchResults)
        }
    }

    /// Lottie animation + "No results found" — matches Android's empty state.
    var noResultsState: some View {
        VStack(spacing: 20) {
            Spacer()
            LottieView(
                animationName: "search",
                animationSpeed: 1.0
            )
            .frame(width: 120, height: 120)
            Text("Search for users")
                .font(.system(size: 17, weight: .medium))
                .foregroundStyle(RosettaColors.Adaptive.text)
            Text("Enter username or public key")
                .font(.system(size: 14))
                .foregroundStyle(RosettaColors.Adaptive.textSecondary)
            Spacer()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

    /// Scrollable list of merged search results.
    /// Shows skeleton rows at the bottom while server is still searching.
    func resultsList(results: [SearchUser]) -> some View {
        ScrollView {
            LazyVStack(spacing: 0) {
                ForEach(results, id: \.publicKey) { user in
                    serverUserRow(user)
                    if user.publicKey != results.last?.publicKey {
                        Divider()
                            .padding(.leading, 76)
                            .foregroundStyle(RosettaColors.Adaptive.divider)
                    }
                }

                // Skeleton loading rows while server search in progress
                if viewModel.isServerSearching {
                    searchSkeletonRows
                }

                Spacer().frame(height: 80)
            }
        }
        .scrollDismissesKeyboard(.immediately)
    }

    /// Inline skeleton rows (3 shimmer placeholders) shown below existing results.
    private var searchSkeletonRows: some View {
        ForEach(0..<3, id: \.self) { _ in
            SearchSkeletonRow()
        }
    }
}

// MARK: - Recent Searches

private extension ChatListSearchContent {
    @ViewBuilder
    var recentSearchesSection: some View {
        ScrollView {
            VStack(spacing: 0) {
                // Horizontal scrollable favorite contacts row
                FavoriteContactsRowSearch(onOpenDialog: onOpenDialog)

                if viewModel.recentSearches.isEmpty {
                    searchPlaceholderInline
                } else {
                    HStack {
                        Text("RECENT")
                            .font(.system(size: 13))
                            .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                        Spacer()
                        Button { viewModel.clearRecentSearches() } label: {
                            Text("Clear")
                                .font(.system(size: 13))
                                .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                        }
                    }
                    .padding(.horizontal, 16)
                    .padding(.top, 20)
                    .padding(.bottom, 6)

                    ForEach(viewModel.recentSearches, id: \.publicKey) { recent in
                        recentRow(recent)
                        if recent.publicKey != viewModel.recentSearches.last?.publicKey {
                            Divider()
                                .padding(.leading, 68)
                                .foregroundStyle(RosettaColors.Adaptive.divider)
                        }
                    }
                }

                Spacer().frame(height: 120)
            }
        }
        .scrollDismissesKeyboard(.immediately)
    }

    var searchPlaceholderInline: some View {
        VStack(spacing: 16) {
            LottieView(
                animationName: "search",
                animationSpeed: 1.0
            )
            .frame(width: 120, height: 120)
            .padding(.top, 60)

            Text("Search for users")
                .font(.system(size: 17, weight: .semibold))
                .foregroundStyle(RosettaColors.Adaptive.textSecondary)

            Text("Find people by username or public key")
                .font(.system(size: 15))
                .foregroundStyle(RosettaColors.Adaptive.textTertiary)
                .multilineTextAlignment(.center)
                .padding(.horizontal, 40)
        }
        .frame(maxWidth: .infinity)
    }

    func recentRow(_ user: RecentSearch) -> some View {
        let isSelf = user.publicKey == SessionManager.shared.currentPublicKey
        let initials = isSelf ? "S" : RosettaColors.initials(
            name: user.title, publicKey: user.publicKey
        )
        let colorIdx = RosettaColors.avatarColorIndex(for: user.title, publicKey: user.publicKey)
        let effectiveVerified = Self.effectiveVerifiedLevel(
            verified: user.verified, title: user.title,
            username: user.username, publicKey: user.publicKey
        )

        return Button {
            onOpenDialog(ChatRoute(recent: user))
        } label: {
            HStack(spacing: 10) {
                AvatarView(
                    initials: initials, colorIndex: colorIdx,
                    size: 42, isSavedMessages: isSelf
                )

                VStack(alignment: .leading, spacing: 1) {
                    HStack(spacing: 4) {
                        Text(isSelf ? "Saved Messages" : (
                            user.title.isEmpty
                            ? String(user.publicKey.prefix(16)) + "..."
                            : user.title
                        ))
                            .font(.system(size: 17, weight: .medium))
                            .foregroundStyle(RosettaColors.Adaptive.text)
                            .lineLimit(1)
                        if !isSelf && effectiveVerified > 0 {
                            VerifiedBadge(
                                verified: effectiveVerified,
                                size: 14
                            )
                        }
                    }
                    if !isSelf {
                        let dialog = DialogRepository.shared.dialogs[user.publicKey]
                        let isOnline = dialog?.isOnline ?? false
                        Text(isOnline ? "online" : "offline")
                            .font(.system(size: 13))
                            .foregroundStyle(isOnline
                                ? RosettaColors.primaryBlue
                                : RosettaColors.Adaptive.textSecondary)
                            .lineLimit(1)
                    }
                }
                Spacer()
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 5)
            .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
    }

    /// Desktop parity: compute effective verified level — server value + client heuristic.
    private static func effectiveVerifiedLevel(
        verified: Int, title: String, username: String, publicKey: String
    ) -> Int {
        if verified > 0 { return verified }
        if title.caseInsensitiveCompare("Rosetta") == .orderedSame { return 1 }
        if username.caseInsensitiveCompare("rosetta") == .orderedSame { return 1 }
        if title.caseInsensitiveCompare("freddy") == .orderedSame { return 1 }
        if username.caseInsensitiveCompare("freddy") == .orderedSame { return 1 }
        if SystemAccounts.isSystemAccount(publicKey) { return 1 }
        return 0
    }
}

// MARK: - Server User Row

private extension ChatListSearchContent {
    func serverUserRow(_ user: SearchUser) -> some View {
        let isSelf = user.publicKey == SessionManager.shared.currentPublicKey
        let initials = isSelf ? "S" : RosettaColors.initials(
            name: user.title, publicKey: user.publicKey
        )
        let colorIdx = RosettaColors.avatarColorIndex(for: user.title, publicKey: user.publicKey)

        return Button {
            viewModel.addToRecent(user)
            onOpenDialog(ChatRoute(user: user))
        } label: {
            HStack(spacing: 12) {
                AvatarView(
                    initials: initials, colorIndex: colorIdx,
                    size: 48, isOnline: user.online == 0,
                    isSavedMessages: isSelf
                )

                VStack(alignment: .leading, spacing: 2) {
                    HStack(spacing: 4) {
                        Text(isSelf ? "Saved Messages" : (
                            user.title.isEmpty
                            ? String(user.publicKey.prefix(10))
                            : user.title
                        ))
                            .font(.system(size: 16, weight: .medium))
                            .foregroundStyle(RosettaColors.Adaptive.text)
                            .lineLimit(1)
                        if !isSelf && (user.verified > 0 || isRosettaOfficial(user)) {
                            VerifiedBadge(
                                verified: user.verified > 0 ? user.verified : 1,
                                size: 16
                            )
                        }
                    }
                    Text(isSelf ? "Notes" : (
                        user.username.isEmpty
                        ? "@\(String(user.publicKey.prefix(10)))..."
                        : "@\(user.username)"
                    ))
                        .font(.system(size: 14))
                        .foregroundStyle(RosettaColors.Adaptive.textSecondary)
                        .lineLimit(1)
                }
                Spacer()
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 12)
            .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
    }
}

// MARK: - Favorite Contacts Row (observation-isolated)

/// Horizontal scrollable avatar row for active search state.
/// Isolated child view so that `DialogRepository.shared.sortedDialogs` observation
/// does NOT propagate to `ChatListSearchContent`'s parent.
private struct FavoriteContactsRowSearch: View {
    var onOpenDialog: (ChatRoute) -> Void

    var body: some View {
        let dialogs = DialogRepository.shared.sortedDialogs.prefix(10)
        if !dialogs.isEmpty {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 4) {
                    ForEach(Array(dialogs), id: \.id) { dialog in
                        Button {
                            onOpenDialog(ChatRoute(dialog: dialog))
                        } label: {
                            VStack(spacing: 4) {
                                AvatarView(
                                    initials: dialog.initials,
                                    colorIndex: dialog.avatarColorIndex,
                                    size: 62,
                                    isOnline: dialog.isOnline,
                                    isSavedMessages: dialog.isSavedMessages,
                                    image: dialog.isSavedMessages ? nil : AvatarRepository.shared.loadAvatar(publicKey: dialog.opponentKey)
                                )

                                Text(dialog.isSavedMessages ? "Saved" : dialog.opponentTitle.components(separatedBy: " ").first ?? "")
                                    .font(.system(size: 11))
                                    .tracking(0.06)
                                    .foregroundStyle(RosettaColors.Adaptive.text)
                                    .lineLimit(1)
                                    .frame(width: 78)
                            }
                            .frame(width: 78)
                        }
                        .buttonStyle(.plain)
                    }
                }
                .padding(.horizontal, 2)
            }
            .padding(.top, 12)
        }
    }
}
