import Foundation import SwiftUI import UniformTypeIdentifiers @MainActor final class ImportFlowViewModel: ObservableObject { @Published var template = MoodwellStateOfMindTemplate.template @Published var entries: [MoodwellEntry] = [] @Published var sourceKeys: [String] = [] @Published var mapping = MoodwellStateOfMindTemplate.defaultMapping @Published var moodValenceScale: [Int: Double] = [1: -0.8, 2: -0.25, 3: 0.3, 4: 0.8] @Published var dryRunResult: DryRunResult? @Published var isImporting = false @Published var statusMessage = "" @Published var errorMessage: String? let supportedContentTypes: [UTType] = [.json] private let healthKitService = HealthKitService() init() { loadBundledSample() } func loadBundledSample() { guard let url = Bundle.main.url(forResource: "MoodwellData", withExtension: "json") else { errorMessage = String(localized: "error.sample.missing") return } loadFile(from: url) } func loadFile(from url: URL) { do { let data = try Data(contentsOf: url) let payload = try JSONDecoder().decode(MoodwellPayload.self, from: data) entries = payload.mymoods if let firstEntry = payload.mymoods.first { sourceKeys = Array(firstEntry.sourceDictionary.keys).sorted() } else { sourceKeys = [] } dryRunResult = nil statusMessage = String.localizedStringWithFormat( NSLocalizedString("status.loaded", comment: ""), entries.count ) errorMessage = nil } catch { errorMessage = String(localized: "error.load.file") + " \(error.localizedDescription)" } } func runDryRun() { let result = MoodwellStateOfMindTemplate.makeDrafts(entries: entries, mapping: mapping, moodValenceScale: moodValenceScale) dryRunResult = result if result.errors.isEmpty { statusMessage = String.localizedStringWithFormat( NSLocalizedString("status.dryrun.success", comment: ""), result.drafts.count ) } else { statusMessage = String.localizedStringWithFormat( NSLocalizedString("status.dryrun.withErrors", comment: ""), result.errors.count ) } } func commitImport() async { guard let dryRunResult else { errorMessage = String(localized: "error.dryrun.required") return } guard dryRunResult.errors.isEmpty else { errorMessage = String(localized: "error.dryrun.fix") return } isImporting = true defer { isImporting = false } do { try await healthKitService.requestWriteAccessForStateOfMind() try await healthKitService.save(dryRunResult.drafts) statusMessage = String.localizedStringWithFormat( NSLocalizedString("status.import.success", comment: ""), dryRunResult.drafts.count ) errorMessage = nil } catch { errorMessage = String(localized: "error.import.failed") + " \(error.localizedDescription)" } } }