@preconcurrency import ApplicationServices
import CoreGraphics
import Foundation

private let axTrustedCheckOptionPromptKey =
    kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String

public enum PermissionKind: String, CaseIterable, Equatable, Sendable {
    case accessibility
    case screenRecording
}

public enum PermissionStatus: Equatable, Sendable {
    case granted
    case notGranted
}

public protocol SystemPermissionChecking {
    func status(for kind: PermissionKind) -> PermissionStatus
}

public protocol SystemPermissionRequesting {
    @discardableResult
    func request(_ kind: PermissionKind) -> PermissionStatus
}

public protocol SystemPermissionManaging: SystemPermissionChecking, SystemPermissionRequesting {}

public struct SystemPermissionChecker: SystemPermissionManaging {
    public init() {}

    public func status(for kind: PermissionKind) -> PermissionStatus {
        switch kind {
        case .accessibility:
            return AXIsProcessTrusted() ? .granted : .notGranted
        case .screenRecording:
            return CGPreflightScreenCaptureAccess() ? .granted : .notGranted
        }
    }

    @discardableResult
    public func request(_ kind: PermissionKind) -> PermissionStatus {
        switch kind {
        case .accessibility:
            let options = [axTrustedCheckOptionPromptKey: true] as CFDictionary
            return AXIsProcessTrustedWithOptions(options) ? .granted : .notGranted
        case .screenRecording:
            return CGRequestScreenCaptureAccess() ? .granted : .notGranted
        }
    }
}
