import Foundation import Observation enum DebugSupervisionMode: String, CaseIterable, Identifiable { case none case forceSupervised case forceUnsupervised var id: String { rawValue } var title: String { switch self { case .none: return "Aus" case .forceSupervised: return "Force Supervised" case .forceUnsupervised: return "Force Unsupervised" } } } @MainActor @Observable final class WizardModel { var step: WizardStep = .welcome var device: DeviceState? var supervisionLog: [String] = [] var supervisionRunning: Bool = false var supervisionError: String? var enrollmentLog: [String] = [] var enrollmentRunning: Bool = false var enrollmentError: String? var configureLog: [String] = [] var configureRunning: Bool = false var configureError: String? var showAdvancedLogs: Bool = false var cooldownEndsAt: Date? // Debug-Reset State var supervisionMode: DebugSupervisionMode = .none var resetRunning: Bool = false var resetStatus: String? var resetAll: Bool = true var resetEnrollmentProfile: Bool = true var resetLockProfile: Bool = true var resetApp: Bool = true func advance() { if let next = WizardStep(rawValue: step.rawValue + 1) { step = next } } func goTo(_ s: WizardStep) { step = s } func reset() { step = .welcome device = nil supervisionLog = [] enrollmentLog = [] configureLog = [] supervisionError = nil enrollmentError = nil configureError = nil showAdvancedLogs = false cooldownEndsAt = nil resetStatus = nil } func startDebugReset() { guard device != nil else { resetStatus = "Kein iPhone erkannt." return } resetRunning = true resetStatus = "Führe Debug-Reset aus …" Task { do { var changes: [String] = [] let removeEnrollment = resetAll || resetEnrollmentProfile let removeLock = resetAll || resetLockProfile let removeApp = resetAll || resetApp let installedProfileIDs = await DeviceDetector.installedProfileIDs() var profileIDs: [String] = [] if removeEnrollment, installedProfileIDs.contains(DeviceState.enrollmentProfileID) { profileIDs.append(DeviceState.enrollmentProfileID) } if removeLock, installedProfileIDs.contains(DeviceState.lockProfileID) { profileIDs.append(DeviceState.lockProfileID) } if !profileIDs.isEmpty { try await DeviceDetector.removeProfiles(identifiers: profileIDs) changes.append("Profile gelöscht: \(profileIDs.joined(separator: ", "))") } if removeApp { try await DeviceDetector.removeApp(bundleID: "org.rebreak.app") changes.append("App gelöscht: org.rebreak.app") } switch supervisionMode { case .forceSupervised: _ = try await SuperviseRunner.supervise(verbose: false) { _ in } changes.append("Mode gesetzt: supervised") case .forceUnsupervised: _ = try await SuperviseRunner.unsupervise { _ in } changes.append("Mode gesetzt: unsupervised") case .none: break } let nowInstalledProfiles = await DeviceDetector.installedProfileIDs() let nowApps = await DeviceDetector.installedAppBundleIDs() let status = await DeviceDetector.readSupervisionStatus() await MainActor.run { if changes.isEmpty { resetStatus = "Keine Aktion gewählt." } else { resetStatus = "✓ \(changes.joined(separator: " · "))" } if var device = self.device { device.installedProfileIDs = nowInstalledProfiles device.installedAppBundleIDs = nowApps device.isSupervised = status.isSupervised device.supervisorOrgName = status.organizationName device.isFmiOn = status.findMyEnabled device.isEnrolled = nowInstalledProfiles.contains(DeviceState.enrollmentProfileID) if !nowApps.contains("org.rebreak.app") { device.isManaged = false } if !nowInstalledProfiles.contains(DeviceState.lockProfileID) { device.isFilterActive = false } self.device = device } resetRunning = false } } catch { await MainActor.run { resetStatus = "✗ Reset fehlgeschlagen: \(error.localizedDescription)" resetRunning = false } } } } }