import Foundation
import AppKit

/// Service für Mac-DNS-Profile-Download + Installation.
enum MacProfileInstaller {
    
    enum InstallerError: Error, LocalizedError {
        case noRegistration
        case downloadFailed(String)
        case installFailed(String)
        
        var errorDescription: String? {
            switch self {
            case .noRegistration:
                return "Mac ist nicht registriert. Bitte zuerst registrieren."
            case .downloadFailed(let msg):
                return "Profile-Download fehlgeschlagen: \(msg)"
            case .installFailed(let msg):
                return "Profile-Installation fehlgeschlagen: \(msg)"
            }
        }
    }
    
    /// Lädt Mac-DNS-Profile von Backend und öffnet es in System Settings → Profiles.
    /// Ab macOS 15+ ist `profiles install` für Configuration Profiles entfernt
    /// ("profiles tool no longer supports installs. Use System Settings
    /// Profiles to add configuration profiles."). Einzig zulässiger Weg ohne
    /// MDM-Enrollment: NSWorkspace öffnet die .mobileconfig → Profiles-Pane
    /// erscheint → User muss manuell „Installieren" klicken + Admin-PW geben.
    static func downloadAndInstall(registration: MagicRegistration) async throws {
        // 1. Download profile
        let profileURL: URL
        do {
            profileURL = try await MagicAPIClient.shared.downloadProfile(token: registration.dnsToken)
        } catch {
            throw InstallerError.downloadFailed(error.localizedDescription)
        }
        
        // 2. Open in System Settings → Profiles (user must confirm in UI)
        let opened = await MainActor.run {
            NSWorkspace.shared.open(profileURL)
        }
        
        if !opened {
            try? FileManager.default.removeItem(at: profileURL)
            throw InstallerError.installFailed(
                "System Settings konnte das Profil nicht öffnen. Datei liegt unter: \(profileURL.path)"
            )
        }
        
        // NICHT löschen — System Settings braucht die Datei evtl. noch.
        // OS räumt /tmp selbst auf.
    }
    
    /// Prüft ob ReBreak-DNS-Profile bereits installiert ist.
    /// Verwendet `profiles show -type configuration`.
    static func isInstalled() async -> Bool {
        guard let result = try? await ProcessRunner.run(
            "/usr/bin/profiles",
            arguments: ["show", "-type", "configuration"]
        ), result.exitCode == 0 else {
            return false
        }
        
        // Suche nach PayloadIdentifier pattern org.rebreak.protection.dns.filter*
        return result.stdout.localizedCaseInsensitiveContains("org.rebreak.protection.dns.filter")
            || result.stdout.localizedCaseInsensitiveContains("org.rebreak.protection.profile")
    }
    
    // MARK: - Debug only

#if DEBUG
    /// Entfernt ReBreak-DNS-Profile.
    /// NUR in Debug-Builds verfügbar — darf nicht im Release-Binary landen.
    static func remove() async throws {
        // 1. Find identifier
        guard let result = try? await ProcessRunner.run(
            "/usr/bin/profiles",
            arguments: ["show", "-type", "configuration"]
        ), result.exitCode == 0 else {
            return
        }

        // Parse identifier aus Output (format: "   <identifier>: <displayName>")
        let lines = result.stdout.split(separator: "\n")
        var identifier: String?

        for line in lines {
            let trimmed = line.trimmingCharacters(in: .whitespaces)
            if trimmed.hasPrefix("org.rebreak.protection.profile") {
                // Format: "org.rebreak.protection.profile.abc123: ReBreak Protection"
                identifier = trimmed.split(separator: ":").first.map(String.init)
                break
            }
        }

        guard let id = identifier else { return }

        // 2. Remove profile
        let removeResult = try await ProcessRunner.run(
            "/usr/bin/profiles",
            arguments: ["remove", "-identifier", id]
        )

        if removeResult.exitCode != 0 {
            throw InstallerError.installFailed(removeResult.stderr)
        }
    }
#endif
}
