import Foundation
import SwiftData

/// Turns a SwiftData save failure into a message a view can show.
///
/// `assertionFailure` is compiled out under `-O`, so a `catch` that only asserts
/// discards the error entirely in Release builds and lets the caller continue as
/// if the write had succeeded. These helpers hand the failure back instead.
enum PersistenceSave {
    static func message(for error: Error) -> String {
        "Your change could not be saved: \(error.localizedDescription)"
    }
}

extension ModelContext {
    /// Saves pending changes and returns a user-facing message when the save fails.
    ///
    /// A failed save rolls the context back so the in-memory state matches what is
    /// actually on disk. Without it a view keeps showing an inserted or edited
    /// object that would be gone on the next launch.
    func saveOrRollback() -> String? {
        saveOrRollback { try save() }
    }

    /// Testing seam: `performSave` lets tests drive the failure path, which a real
    /// save on an in-memory store cannot reach.
    func saveOrRollback(performSave: () throws -> Void) -> String? {
        do {
            try performSave()
            return nil
        } catch {
            rollback()
            return PersistenceSave.message(for: error)
        }
    }
}
