// Screenshot Manager APIs (macOS 14.0+)

import CoreGraphics
import CoreMedia
import Foundation
import ScreenCaptureKit
import UniformTypeIdentifiers

// MARK: - Screenshot Manager (macOS 14.0+)

@available(macOS 14.0, *)
@_cdecl("sc_screenshot_manager_capture_image")
public func captureScreenshot(
    _ contentFilter: OpaquePointer,
    _ config: OpaquePointer,
    _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
    _ userData: UnsafeMutableRawPointer?
) {
    let filter: SCContentFilter = unretained(contentFilter)
    let configuration: SCStreamConfiguration = unretained(config)

    Task {
        do {
            let image = try await SCScreenshotManager.captureImage(
                contentFilter: filter,
                configuration: configuration
            )
            callback(retain(image), nil, userData)
        } catch {
            let bridgeError = SCBridgeError.screenshotError(error.localizedDescription)
            bridgeError.description.withCString { callback(nil, $0, userData) }
        }
    }
}

@available(macOS 14.0, *)
@_cdecl("sc_screenshot_manager_capture_sample_buffer")
public func captureScreenshotSampleBuffer(
    _ contentFilter: OpaquePointer,
    _ config: OpaquePointer,
    _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
    _ userData: UnsafeMutableRawPointer?
) {
    let filter: SCContentFilter = unretained(contentFilter)
    let configuration: SCStreamConfiguration = unretained(config)

    Task {
        do {
            let sampleBuffer = try await SCScreenshotManager.captureSampleBuffer(
                contentFilter: filter,
                configuration: configuration
            )
            let retained = Unmanaged.passRetained(sampleBuffer as AnyObject)
            callback(OpaquePointer(retained.toOpaque()), nil, userData)
        } catch {
            let bridgeError = SCBridgeError.screenshotError(error.localizedDescription)
            bridgeError.description.withCString { callback(nil, $0, userData) }
        }
    }
}

// MARK: - Capture image in rect (macOS 15.2+)

#if SCREENCAPTUREKIT_HAS_MACOS15_SDK
    @_cdecl("sc_screenshot_manager_capture_image_in_rect")
    public func captureScreenshotInRect(
        _ x: Double,
        _ y: Double,
        _ width: Double,
        _ height: Double,
        _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
        _ userData: UnsafeMutableRawPointer?
    ) {
        if #available(macOS 15.2, *) {
            let rect = CGRect(x: x, y: y, width: width, height: height)
            Task {
                do {
                    let image = try await SCScreenshotManager.captureImage(in: rect)
                    callback(retain(image), nil, userData)
                } catch {
                    let bridgeError = SCBridgeError.screenshotError(error.localizedDescription)
                    bridgeError.description.withCString { callback(nil, $0, userData) }
                }
            }
        } else {
            let bridgeError = SCBridgeError.screenshotError("captureImageInRect requires macOS 15.2+")
            bridgeError.description.withCString { callback(nil, $0, userData) }
        }
    }
#else
    @_cdecl("sc_screenshot_manager_capture_image_in_rect")
    public func captureScreenshotInRect(
        _: Double,
        _: Double,
        _: Double,
        _: Double,
        _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
        _ userData: UnsafeMutableRawPointer?
    ) {
        let bridgeError = SCBridgeError.screenshotError("captureImageInRect requires macOS 15.2+")
        bridgeError.description.withCString { callback(nil, $0, userData) }
    }
#endif

// MARK: - SCScreenshotConfiguration (macOS 26.0+)

#if SCREENCAPTUREKIT_HAS_MACOS26_SDK
    @_cdecl("sc_screenshot_configuration_create")
    public func createScreenshotConfiguration() -> OpaquePointer? {
        if #available(macOS 26.0, *) {
            let config = SCScreenshotConfiguration()
            return retain(config)
        }
        return nil
    }

    @_cdecl("sc_screenshot_configuration_set_width")
    public func setScreenshotConfigurationWidth(_ config: OpaquePointer, _ width: Int) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.width = width
        }
    }

    @_cdecl("sc_screenshot_configuration_set_height")
    public func setScreenshotConfigurationHeight(_ config: OpaquePointer, _ height: Int) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.height = height
        }
    }

    @_cdecl("sc_screenshot_configuration_set_shows_cursor")
    public func setScreenshotConfigurationShowsCursor(_ config: OpaquePointer, _ showsCursor: Bool) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.showsCursor = showsCursor
        }
    }

    @_cdecl("sc_screenshot_configuration_set_source_rect")
    public func setScreenshotConfigurationSourceRect(_ config: OpaquePointer, _ x: Double, _ y: Double, _ width: Double, _ height: Double) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.sourceRect = CGRect(x: x, y: y, width: width, height: height)
        }
    }

    @_cdecl("sc_screenshot_configuration_set_destination_rect")
    public func setScreenshotConfigurationDestinationRect(_ config: OpaquePointer, _ x: Double, _ y: Double, _ width: Double, _ height: Double) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.destinationRect = CGRect(x: x, y: y, width: width, height: height)
        }
    }

    @_cdecl("sc_screenshot_configuration_set_ignore_shadows")
    public func setScreenshotConfigurationIgnoreShadows(_ config: OpaquePointer, _ ignoreShadows: Bool) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.ignoreShadows = ignoreShadows
        }
    }

    @_cdecl("sc_screenshot_configuration_set_ignore_clipping")
    public func setScreenshotConfigurationIgnoreClipping(_ config: OpaquePointer, _ ignoreClipping: Bool) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.ignoreClipping = ignoreClipping
        }
    }

    @_cdecl("sc_screenshot_configuration_set_include_child_windows")
    public func setScreenshotConfigurationIncludeChildWindows(_ config: OpaquePointer, _ includeChildWindows: Bool) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            c.includeChildWindows = includeChildWindows
        }
    }

    @_cdecl("sc_screenshot_configuration_set_display_intent")
    public func setScreenshotConfigurationDisplayIntent(_ config: OpaquePointer, _ displayIntent: Int32) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            switch displayIntent {
            case 0: c.displayIntent = .canonical
            case 1: c.displayIntent = .local
            default: break
            }
        }
    }

    @_cdecl("sc_screenshot_configuration_set_dynamic_range")
    public func setScreenshotConfigurationDynamicRange(_ config: OpaquePointer, _ dynamicRange: Int32) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            switch dynamicRange {
            case 0: c.dynamicRange = .sdr
            case 1: c.dynamicRange = .hdr
            case 2: c.dynamicRange = .bothSDRAndHDR
            default: break
            }
        }
    }

    @_cdecl("sc_screenshot_configuration_set_file_url")
    public func setScreenshotConfigurationFileURL(_ config: OpaquePointer, _ path: UnsafePointer<CChar>) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            let pathString = String(cString: path)
            c.fileURL = URL(fileURLWithPath: pathString)
        }
    }

    @_cdecl("sc_screenshot_configuration_release")
    public func releaseScreenshotConfiguration(_ config: OpaquePointer) {
        release(config)
    }

    // MARK: - Content Type Support (macOS 26.0+)

    /// Set the content type (output format) using UTType identifier
    @_cdecl("sc_screenshot_configuration_set_content_type")
    public func setScreenshotConfigurationContentType(_ config: OpaquePointer, _ identifier: UnsafePointer<CChar>) {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            let typeIdentifier = String(cString: identifier)
            if let utType = UTType(typeIdentifier) {
                // UTTypeReference is bridged from UTType
                c.contentType = utType as UTTypeReference
            }
        }
    }

    /// Get the content type (output format) as UTType identifier
    @_cdecl("sc_screenshot_configuration_get_content_type")
    public func getScreenshotConfigurationContentType(_ config: OpaquePointer, _ buffer: UnsafeMutablePointer<CChar>, _ bufferSize: Int) -> Bool {
        if #available(macOS 26.0, *) {
            let c: SCScreenshotConfiguration = unretained(config)
            // UTTypeReference is type-aliased to UTType
            let utType = c.contentType as UTType
            let identifier = utType.identifier
            return identifier.withCString { src in
                strlcpy(buffer, src, bufferSize)
                return true
            }
        }
        return false
    }

    /// Get the number of supported content types
    @_cdecl("sc_screenshot_configuration_get_supported_content_types_count")
    public func getScreenshotConfigurationSupportedContentTypesCount() -> Int {
        if #available(macOS 26.0, *) {
            return SCScreenshotConfiguration.supportedContentTypes.count
        }
        return 0
    }

    /// Get a supported content type at index as UTType identifier
    @_cdecl("sc_screenshot_configuration_get_supported_content_type_at")
    public func getScreenshotConfigurationSupportedContentTypeAt(_ index: Int, _ buffer: UnsafeMutablePointer<CChar>, _ bufferSize: Int) -> Bool {
        if #available(macOS 26.0, *) {
            let types = SCScreenshotConfiguration.supportedContentTypes
            guard index >= 0, index < types.count else { return false }
            let identifier = types[index].identifier
            return identifier.withCString { src in
                strlcpy(buffer, src, bufferSize)
                return true
            }
        }
        return false
    }

    // MARK: - SCScreenshotOutput (macOS 26.0+)

    @_cdecl("sc_screenshot_output_get_sdr_image")
    public func getScreenshotOutputSDRImage(_ output: OpaquePointer) -> OpaquePointer? {
        if #available(macOS 26.0, *) {
            let o: SCScreenshotOutput = unretained(output)
            if let image = o.sdrImage {
                return retain(image)
            }
        }
        return nil
    }

    @_cdecl("sc_screenshot_output_get_hdr_image")
    public func getScreenshotOutputHDRImage(_ output: OpaquePointer) -> OpaquePointer? {
        if #available(macOS 26.0, *) {
            let o: SCScreenshotOutput = unretained(output)
            if let image = o.hdrImage {
                return retain(image)
            }
        }
        return nil
    }

    @_cdecl("sc_screenshot_output_get_file_url")
    public func getScreenshotOutputFileURL(_ output: OpaquePointer, _ buffer: UnsafeMutablePointer<CChar>, _ bufferSize: Int) -> Bool {
        if #available(macOS 26.0, *) {
            let o: SCScreenshotOutput = unretained(output)
            if let url = o.fileURL, let pathString = url.path as String?, let cString = pathString.cString(using: .utf8) {
                strncpy(buffer, cString, bufferSize - 1)
                buffer[bufferSize - 1] = 0
                return true
            }
        }
        return false
    }

    @_cdecl("sc_screenshot_output_release")
    public func releaseScreenshotOutput(_ output: OpaquePointer) {
        release(output)
    }

    // MARK: - New Screenshot Capture API (macOS 26.0+)

    @_cdecl("sc_screenshot_manager_capture_screenshot")
    public func captureScreenshotWithConfiguration(
        _ contentFilter: OpaquePointer,
        _ config: OpaquePointer,
        _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
        _ userData: UnsafeMutableRawPointer?
    ) {
        if #available(macOS 26.0, *) {
            let filter: SCContentFilter = unretained(contentFilter)
            let configuration: SCScreenshotConfiguration = unretained(config)

            Task {
                do {
                    let output = try await SCScreenshotManager.captureScreenshot(
                        contentFilter: filter,
                        configuration: configuration
                    )
                    callback(retain(output), nil, userData)
                } catch {
                    let bridgeError = SCBridgeError.screenshotError(error.localizedDescription)
                    bridgeError.description.withCString { callback(nil, $0, userData) }
                }
            }
        } else {
            let bridgeError = SCBridgeError.screenshotError("captureScreenshot requires macOS 26.0+")
            bridgeError.description.withCString { callback(nil, $0, userData) }
        }
    }

    @_cdecl("sc_screenshot_manager_capture_screenshot_in_rect")
    public func captureScreenshotInRectWithConfiguration(
        _ x: Double,
        _ y: Double,
        _ width: Double,
        _ height: Double,
        _ config: OpaquePointer,
        _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
        _ userData: UnsafeMutableRawPointer?
    ) {
        if #available(macOS 26.0, *) {
            let rect = CGRect(x: x, y: y, width: width, height: height)
            let configuration: SCScreenshotConfiguration = unretained(config)

            Task {
                do {
                    let output = try await SCScreenshotManager.captureScreenshot(
                        rect: rect,
                        configuration: configuration
                    )
                    callback(retain(output), nil, userData)
                } catch {
                    let bridgeError = SCBridgeError.screenshotError(error.localizedDescription)
                    bridgeError.description.withCString { callback(nil, $0, userData) }
                }
            }
        } else {
            let bridgeError = SCBridgeError.screenshotError("captureScreenshotInRect requires macOS 26.0+")
            bridgeError.description.withCString { callback(nil, $0, userData) }
        }
    }
#else
    // Stubs for older compilers
    @_cdecl("sc_screenshot_configuration_create")
    public func createScreenshotConfiguration() -> OpaquePointer? { nil }

    @_cdecl("sc_screenshot_configuration_set_width")
    public func setScreenshotConfigurationWidth(_: OpaquePointer, _: Int) {}

    @_cdecl("sc_screenshot_configuration_set_height")
    public func setScreenshotConfigurationHeight(_: OpaquePointer, _: Int) {}

    @_cdecl("sc_screenshot_configuration_set_shows_cursor")
    public func setScreenshotConfigurationShowsCursor(_: OpaquePointer, _: Bool) {}

    @_cdecl("sc_screenshot_configuration_set_source_rect")
    public func setScreenshotConfigurationSourceRect(_: OpaquePointer, _: Double, _: Double, _: Double, _: Double) {}

    @_cdecl("sc_screenshot_configuration_set_destination_rect")
    public func setScreenshotConfigurationDestinationRect(_: OpaquePointer, _: Double, _: Double, _: Double, _: Double) {}

    @_cdecl("sc_screenshot_configuration_set_ignore_shadows")
    public func setScreenshotConfigurationIgnoreShadows(_: OpaquePointer, _: Bool) {}

    @_cdecl("sc_screenshot_configuration_set_ignore_clipping")
    public func setScreenshotConfigurationIgnoreClipping(_: OpaquePointer, _: Bool) {}

    @_cdecl("sc_screenshot_configuration_set_include_child_windows")
    public func setScreenshotConfigurationIncludeChildWindows(_: OpaquePointer, _: Bool) {}

    @_cdecl("sc_screenshot_configuration_set_display_intent")
    public func setScreenshotConfigurationDisplayIntent(_: OpaquePointer, _: Int32) {}

    @_cdecl("sc_screenshot_configuration_set_dynamic_range")
    public func setScreenshotConfigurationDynamicRange(_: OpaquePointer, _: Int32) {}

    @_cdecl("sc_screenshot_configuration_set_file_url")
    public func setScreenshotConfigurationFileURL(_: OpaquePointer, _: UnsafePointer<CChar>) {}

    @_cdecl("sc_screenshot_configuration_release")
    public func releaseScreenshotConfiguration(_: OpaquePointer) {}

    @_cdecl("sc_screenshot_output_get_sdr_image")
    public func getScreenshotOutputSDRImage(_: OpaquePointer) -> OpaquePointer? { nil }

    @_cdecl("sc_screenshot_output_get_hdr_image")
    public func getScreenshotOutputHDRImage(_: OpaquePointer) -> OpaquePointer? { nil }

    @_cdecl("sc_screenshot_output_get_file_url")
    public func getScreenshotOutputFileURL(_: OpaquePointer, _: UnsafeMutablePointer<CChar>, _: Int) -> Bool { false }

    @_cdecl("sc_screenshot_output_release")
    public func releaseScreenshotOutput(_: OpaquePointer) {}

    @_cdecl("sc_screenshot_manager_capture_screenshot")
    public func captureScreenshotWithConfiguration(
        _: OpaquePointer,
        _: OpaquePointer,
        _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
        _ userData: UnsafeMutableRawPointer?
    ) {
        let bridgeError = SCBridgeError.screenshotError("captureScreenshot requires macOS 26.0+")
        bridgeError.description.withCString { callback(nil, $0, userData) }
    }

    @_cdecl("sc_screenshot_manager_capture_screenshot_in_rect")
    public func captureScreenshotInRectWithConfiguration(
        _: Double,
        _: Double,
        _: Double,
        _: Double,
        _: OpaquePointer,
        _ callback: @escaping @convention(c) (OpaquePointer?, UnsafePointer<CChar>?, UnsafeMutableRawPointer?) -> Void,
        _ userData: UnsafeMutableRawPointer?
    ) {
        let bridgeError = SCBridgeError.screenshotError("captureScreenshotInRect requires macOS 26.0+")
        bridgeError.description.withCString { callback(nil, $0, userData) }
    }

    @_cdecl("sc_screenshot_configuration_set_content_type")
    public func setScreenshotConfigurationContentType(_: OpaquePointer, _: UnsafePointer<CChar>) {}

    @_cdecl("sc_screenshot_configuration_get_content_type")
    public func getScreenshotConfigurationContentType(_: OpaquePointer, _: UnsafeMutablePointer<CChar>, _: Int) -> Bool { false }

    @_cdecl("sc_screenshot_configuration_get_supported_content_types_count")
    public func getScreenshotConfigurationSupportedContentTypesCount() -> Int { 0 }

    @_cdecl("sc_screenshot_configuration_get_supported_content_type_at")
    public func getScreenshotConfigurationSupportedContentTypeAt(_: Int, _: UnsafeMutablePointer<CChar>, _: Int) -> Bool { false }
#endif
