import Foundation import CoreBluetooth import BitFoundation /// Represents a peer in the BitChat network with all associated metadata struct BitchatPeer: Equatable { let peerID: PeerID // Hex-encoded peer ID let noisePublicKey: Data let nickname: String let isConnected: Bool let isReachable: Bool // Favorite-related properties var favoriteStatus: FavoritesPersistenceService.FavoriteRelationship? // Nostr identity (if known) var nostrPublicKey: String? // Connection state enum ConnectionState { case bluetoothConnected case meshReachable // Seen via mesh recently, not directly connected case nostrAvailable // Mutual favorite, reachable via Nostr case offline // Not connected via any transport } var connectionState: ConnectionState { if isConnected { return .bluetoothConnected } else if isReachable { return .meshReachable } else if favoriteStatus?.isMutual == true { // Mutual favorites can communicate via Nostr when offline return .nostrAvailable } else { return .offline } } var isFavorite: Bool { favoriteStatus?.isFavorite ?? false } var isMutualFavorite: Bool { favoriteStatus?.isMutual ?? false } var theyFavoritedUs: Bool { favoriteStatus?.theyFavoritedUs ?? false } // Display helpers var displayName: String { nickname.isEmpty ? String(peerID.id.prefix(8)) : nickname } var statusIcon: String { switch connectionState { case .bluetoothConnected: return "📻" // Radio icon for mesh connection case .meshReachable: return "📡" // Antenna for mesh reachable case .nostrAvailable: return "🌐" // Purple globe for Nostr case .offline: if theyFavoritedUs && !isFavorite { return "🌙" // Crescent moon - they favorited us but we didn't reciprocate } else { return "" } } } // Initialize from mesh service data init( peerID: PeerID, noisePublicKey: Data, nickname: String, lastSeen _: Date = Date(), isConnected: Bool = false, isReachable: Bool = false ) { self.peerID = peerID self.noisePublicKey = noisePublicKey self.nickname = nickname self.isConnected = isConnected self.isReachable = isReachable // Load favorite status - will be set later by the manager self.favoriteStatus = nil self.nostrPublicKey = nil } static func == (lhs: BitchatPeer, rhs: BitchatPeer) -> Bool { lhs.peerID == rhs.peerID } }