import Foundation
import Observation

#if DEBUG
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"
        }
    }
}
#endif

@MainActor
@Observable
final class WizardModel {
    var step: WizardStep = .macRegistration
    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?

#if DEBUG
    // Debug-Reset State — nur in Debug-Builds vorhanden
    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
#endif

    // Auth + Magic State
    var authSession: AuthSession?
    var showingLogin: Bool = false
    var showingHub: Bool = false
    var showingManageBindings: Bool = false
    var magicRegistration: MagicRegistration?
    var registrationError: String?
    
    init() {
        // Load existing session from keychain
        authSession = AuthService.shared.currentSession()
        showingLogin = (authSession == nil)
        // Nach Login direkt zum Hub statt Mac-Auto-Registrierung
        showingHub = (authSession != nil)
    }

    func advance() {
        if let next = WizardStep(rawValue: step.rawValue + 1) {
            step = next
        }
    }

    func goTo(_ s: WizardStep) {
        step = s
    }
    
    // MARK: - Mac Registration
    
    /// Registriert den aktuellen Mac im Backend.
    /// Wirft MagicError.limitReached falls Device-Limit erreicht.
    func registerMac() async throws {
        registrationError = nil
        
        do {
            let macInfo = try MacDeviceDetector.detect()
            
            let registration = try await MagicAPIClient.shared.register(
                deviceId: macInfo.deviceId,
                hostname: macInfo.hostname,
                model: macInfo.model,
                osVersion: macInfo.osVersion
            )
            
            magicRegistration = registration
            
        } catch let error as MagicError {
            // Bei limit_reached → öffne ManageBindingsView
            if case .limitReached(_) = error {
                showingManageBindings = true
            }
            registrationError = error.localizedDescription
            throw error
        } catch {
            registrationError = error.localizedDescription
            throw error
        }
    }
    
    func handleLogin(session: AuthSession) {
        authSession = session
        showingLogin = false
        showingHub = true
    }
    
    func handleLogout() async {
        await AuthService.shared.signOut()
        authSession = nil
        showingLogin = true
        showingHub = false
        reset()
    }

    // MARK: - Hub Navigation

    /// User wählt 'iOS-Gerät hinzufügen' im Hub.
    func startIOSFlow() {
        showingHub = false
        step = .welcome
    }

    /// User wählt 'Mac schützen' im Hub.
    func startMacFlow() {
        showingHub = false
        step = .macRegistration
    }

    /// Zurück zur Geräte-Übersicht.
    func returnToHub() {
        reset()
        showingHub = true
    }
    
    func reset() {
        step = .macRegistration
        device = nil
        supervisionLog = []
        enrollmentLog = []
        configureLog = []
        supervisionError = nil
        enrollmentError = nil
        configureError = nil
        showAdvancedLogs = false
        cooldownEndsAt = nil
#if DEBUG
        resetStatus = nil
#endif
        magicRegistration = nil
        registrationError = nil
    }

#if DEBUG
    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
                }
            }
        }
    }
#endif
}
