import Foundation private struct PersistedAddressState: Codable { let selectedId: String? let display: String let latitude: Double? let longitude: Double? } enum SessionStateStore { private static let legacyAddressKey = "session.address.state.v1" private static let addressKeyPrefix = "session.address.state.v2." private static let activeUserKey = "session.active.user.v1" static func makeUserKey(profileId: String?, email: String?) -> String? { let id = (profileId ?? "") .trimmingCharacters(in: .whitespacesAndNewlines) .lowercased() if id.isEmpty == false { return "id:\(id)" } let mail = (email ?? "") .trimmingCharacters(in: .whitespacesAndNewlines) .lowercased() if mail.isEmpty == false { return "email:\(mail)" } return nil } static func setActiveUserKey(_ userKey: String?) { let trimmed = (userKey ?? "").trimmingCharacters(in: .whitespacesAndNewlines) if trimmed.isEmpty { UserDefaults.standard.removeObject(forKey: activeUserKey) } else { UserDefaults.standard.set(trimmed, forKey: activeUserKey) } } static func loadActiveUserKey() -> String? { let value = UserDefaults.standard.string(forKey: activeUserKey)? .trimmingCharacters(in: .whitespacesAndNewlines) if let value, value.isEmpty == false { return value } return nil } private static func addressStorageKey(for userKey: String?) -> String { let key = (userKey ?? loadActiveUserKey() ?? "anonymous") .trimmingCharacters(in: .whitespacesAndNewlines) let safe = key.replacingOccurrences(of: " ", with: "_") return addressKeyPrefix + safe } static func loadAddress() -> AddressState? { let defaults = UserDefaults.standard let activeKey = loadActiveUserKey() let scopedKey = addressStorageKey(for: activeKey) if let data = defaults.data(forKey: scopedKey), let decoded = try? JSONDecoder().decode(PersistedAddressState.self, from: data) { return AddressState( selectedId: decoded.selectedId, display: decoded.display.isEmpty ? "Defina seu endereco" : decoded.display, latitude: decoded.latitude, longitude: decoded.longitude, onboardingMessage: nil ) } // Backward-compatible fallback for data persisted before user scoping. let anonymousKey = addressStorageKey(for: "anonymous") if let data = defaults.data(forKey: anonymousKey), let decoded = try? JSONDecoder().decode(PersistedAddressState.self, from: data) { let recovered = AddressState( selectedId: decoded.selectedId, display: decoded.display.isEmpty ? "Defina seu endereco" : decoded.display, latitude: decoded.latitude, longitude: decoded.longitude, onboardingMessage: nil ) // Migrate anonymous cache into the current active user namespace. if let activeKey, activeKey.isEmpty == false { let payload = PersistedAddressState( selectedId: recovered.selectedId, display: recovered.display, latitude: recovered.latitude, longitude: recovered.longitude ) if let migratedData = try? JSONEncoder().encode(payload) { defaults.set(migratedData, forKey: scopedKey) } } return recovered } guard let data = defaults.data(forKey: legacyAddressKey), let decoded = try? JSONDecoder().decode(PersistedAddressState.self, from: data) else { return nil } let migrated = AddressState( selectedId: decoded.selectedId, display: decoded.display.isEmpty ? "Defina seu endereco" : decoded.display, latitude: decoded.latitude, longitude: decoded.longitude, onboardingMessage: nil ) saveAddress(migrated) defaults.removeObject(forKey: legacyAddressKey) return migrated } static func saveAddress(_ state: AddressState) { let payload = PersistedAddressState( selectedId: state.selectedId, display: state.display, latitude: state.latitude, longitude: state.longitude ) guard let data = try? JSONEncoder().encode(payload) else { return } UserDefaults.standard.set(data, forKey: addressStorageKey(for: nil)) } static func clearAddress() { let defaults = UserDefaults.standard defaults.removeObject(forKey: addressStorageKey(for: nil)) defaults.removeObject(forKey: legacyAddressKey) } static func clearActiveUser() { UserDefaults.standard.removeObject(forKey: activeUserKey) } }