import Foundation /// Timestamped diagnostic log for beacon provisioning. /// Captures every step so we can diagnose failures. @MainActor final class ProvisionLog: ObservableObject { struct Entry: Identifiable { let id = UUID() let timestamp: Date let phase: String // "connect", "discover", "auth", "write", "verify" let message: String let isError: Bool var formatted: String { let t = Self.formatter.string(from: timestamp) let prefix = isError ? "❌" : "✅" return "\(t) [\(phase)] \(prefix) \(message)" } private static let formatter: DateFormatter = { let f = DateFormatter() f.dateFormat = "HH:mm:ss.SSS" return f }() } @Published private(set) var entries: [Entry] = [] private var startTime: Date? /// Clear log for a new provisioning attempt func reset() { entries = [] startTime = Date() } /// Add a log entry func log(_ phase: String, _ message: String, isError: Bool = false) { let entry = Entry(timestamp: Date(), phase: phase, message: message, isError: isError) entries.append(entry) } /// Elapsed time since reset var elapsed: String { guard let start = startTime else { return "0.0s" } let seconds = Date().timeIntervalSince(start) return String(format: "%.1fs", seconds) } /// Full log as shareable text var fullText: String { let header = "Payfrit Beacon Diagnostic Log" let time = "Session: \(elapsed)" let lines = entries.map { $0.formatted } return ([header, time, "---"] + lines).joined(separator: "\n") } }