// SPDX-License-Identifier: AGPL-3.0-or-later

use core::ffi::c_void;
use core::ptr::{self, NonNull};
use std::collections::HashMap;
use std::collections::VecDeque;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};

use crate::encoder_handoff::{
    EncodedBitstream, EncoderDims, EncoderError, EncoderFrameRate, EncoderSubmission, HandoffSlot,
    MAX_BITSTREAM_BYTES, PicParams, VideoToolboxHandoff,
};
use crate::ring::RingError;

type CfDictionaryRef = *const c_void;
type CfStringRef = *const c_void;
type CfNumberRef = *const c_void;
type CfBooleanRef = *const c_void;
type CfAllocatorRef = *const c_void;
type CmTime = OsCmTime;
pub(crate) type CvPixelBufferRef = *mut c_void;
type CmSampleBufferRef = *mut c_void;
type CmBlockBufferRef = *mut c_void;
type VtCompressionSessionRef = *mut c_void;
type VtPixelTransferSessionRef = *mut c_void;
type OsStatus = i32;
pub(crate) type IoSurfaceRef = *mut c_void;

const KCM_VIDEO_CODEC_TYPE_H264: u32 = u32::from_be_bytes(*b"avc1");
#[cfg(test)]
const KCV_PIXEL_FORMAT_TYPE_420_YPCBCR8_BIPLANAR_VIDEO: u32 = u32::from_be_bytes(*b"420v");
const NOERR: OsStatus = 0;
const KCM_TIME_FLAGS_VALID: u32 = 1;
const KCF_NUMBER_SINT32_TYPE: i32 = 3;
const COMPLETION_RING_CAPACITY: usize = 16;
const KVT_INVALID_SESSION_ERR: OsStatus = -12903;
const VT_SESSION_REBUILD_MAX: u64 = 3;
const VT_ENCODE_ATTEMPTS_PER_FRAME_MAX: usize = 2;

#[repr(C)]
#[derive(Copy, Clone)]
struct OsCmTime {
    value: i64,
    timescale: i32,
    flags: u32,
    epoch: i64,
}

#[link(name = "CoreFoundation", kind = "framework")]
unsafe extern "C" {
    static kCFAllocatorDefault: CfAllocatorRef;
    static kCFBooleanTrue: CfBooleanRef;
    fn CFNumberCreate(
        allocator: CfAllocatorRef,
        the_type: i32,
        value_ptr: *const c_void,
    ) -> CfNumberRef;
    fn CFRelease(cf: *const c_void);
    fn CFRetain(cf: *const c_void) -> *const c_void;
}

#[link(name = "CoreVideo", kind = "framework")]
unsafe extern "C" {
    fn CVPixelBufferCreateWithIOSurface(
        allocator: CfAllocatorRef,
        surface: IoSurfaceRef,
        pixel_buffer_attributes: CfDictionaryRef,
        pixel_buffer_out: *mut CvPixelBufferRef,
    ) -> i32;
    fn CVPixelBufferRelease(buffer: CvPixelBufferRef);
}

#[link(name = "CoreMedia", kind = "framework")]
unsafe extern "C" {
    fn CMSampleBufferGetDataBuffer(sample_buffer: CmSampleBufferRef) -> CmBlockBufferRef;
    fn CMBlockBufferGetDataLength(block_buffer: CmBlockBufferRef) -> usize;
    fn CMBlockBufferCopyDataBytes(
        block_buffer: CmBlockBufferRef,
        offset_to_data: usize,
        data_length: usize,
        destination: *mut c_void,
    ) -> OsStatus;
}

#[link(name = "VideoToolbox", kind = "framework")]
unsafe extern "C" {
    static kVTCompressionPropertyKey_RealTime: CfStringRef;
    static kVTCompressionPropertyKey_ProfileLevel: CfStringRef;
    static kVTProfileLevel_H264_Baseline_AutoLevel: CfStringRef;
    static kVTCompressionPropertyKey_AverageBitRate: CfStringRef;
    static kVTCompressionPropertyKey_ExpectedFrameRate: CfStringRef;
    static kVTCompressionPropertyKey_AllowFrameReordering: CfStringRef;
    fn VTCompressionSessionCreate(
        allocator: CfAllocatorRef,
        width: i32,
        height: i32,
        codec_type: u32,
        encoder_specification: CfDictionaryRef,
        source_image_buffer_attributes: CfDictionaryRef,
        compressed_data_allocator: CfAllocatorRef,
        output_callback: Option<VtCompressionOutputCallback>,
        output_callback_refcon: *mut c_void,
        session_out: *mut VtCompressionSessionRef,
    ) -> OsStatus;
    fn VTCompressionSessionEncodeFrame(
        session: VtCompressionSessionRef,
        image_buffer: CvPixelBufferRef,
        presentation_time_stamp: CmTime,
        duration: CmTime,
        frame_properties: CfDictionaryRef,
        source_frame_refcon: *mut c_void,
        info_flags_out: *mut u32,
    ) -> OsStatus;
    fn VTCompressionSessionCompleteFrames(
        session: VtCompressionSessionRef,
        complete_until: CmTime,
    ) -> OsStatus;
    fn VTCompressionSessionInvalidate(session: VtCompressionSessionRef);
    fn VTSessionSetProperty(
        session: *mut c_void,
        property_key: CfStringRef,
        property_value: *const c_void,
    ) -> OsStatus;
    fn VTPixelTransferSessionCreate(
        allocator: CfAllocatorRef,
        session_out: *mut VtPixelTransferSessionRef,
    ) -> OsStatus;
    fn VTPixelTransferSessionTransferImage(
        session: VtPixelTransferSessionRef,
        source: CvPixelBufferRef,
        destination: CvPixelBufferRef,
    ) -> OsStatus;
    fn VTPixelTransferSessionInvalidate(session: VtPixelTransferSessionRef);
}

type VtCompressionOutputCallback = unsafe extern "C" fn(
    output_callback_refcon: *mut c_void,
    source_frame_refcon: *mut c_void,
    status: OsStatus,
    info_flags: u32,
    sample_buffer: CmSampleBufferRef,
);

fn is_invalid_session_error(err: &EncoderError) -> bool {
    match err {
        EncoderError::EncodeFailed { vendor, status } => {
            assert!(!vendor.is_empty(), "encode error vendor non-empty");
            *vendor == "vt-compression-encode" && *status == KVT_INVALID_SESSION_ERR as i64
        }
        _ => false,
    }
}

fn cf_num_i32(v: i32) -> CfNumberRef {
    let ptr: *const i32 = &v;
    unsafe {
        CFNumberCreate(
            kCFAllocatorDefault,
            KCF_NUMBER_SINT32_TYPE,
            ptr as *const c_void,
        )
    }
}

pub struct VtPixelTransfer {
    session: NonNull<c_void>,
}

unsafe impl Send for VtPixelTransfer {}

impl VtPixelTransfer {
    pub fn new() -> Result<Self, EncoderError> {
        let mut raw: VtPixelTransferSessionRef = ptr::null_mut();
        let status = unsafe { VTPixelTransferSessionCreate(kCFAllocatorDefault, &mut raw) };
        if status != NOERR || raw.is_null() {
            return Err(EncoderError::SessionInitFailed {
                vendor: "vt-pixel-transfer",
                status: status as i64,
            });
        }
        let session = NonNull::new(raw).ok_or(EncoderError::SessionInitFailed {
            vendor: "vt-pixel-transfer",
            status: -1,
        })?;
        assert!(
            session.as_ptr() as usize != 0,
            "transfer session non-null after create"
        );
        Ok(Self { session })
    }

    #[allow(clippy::missing_safety_doc)]
    pub unsafe fn transfer(
        &self,
        source: CvPixelBufferRef,
        destination: CvPixelBufferRef,
    ) -> Result<(), EncoderError> {
        assert!(!source.is_null(), "source pixel buffer non-null");
        assert!(!destination.is_null(), "destination pixel buffer non-null");
        let status = unsafe {
            VTPixelTransferSessionTransferImage(self.session.as_ptr(), source, destination)
        };
        if status != NOERR {
            return Err(EncoderError::EncodeFailed {
                vendor: "vt-pixel-transfer",
                status: status as i64,
            });
        }
        Ok(())
    }

    #[allow(clippy::missing_safety_doc)]
    pub unsafe fn wrap_iosurface(
        surface: IoSurfaceRef,
        width: u32,
        height: u32,
    ) -> Result<CvPixelBufferRef, EncoderError> {
        assert!(!surface.is_null(), "wrap source IOSurface non-null");
        assert!(width > 0 && height > 0, "wrap dims positive");
        let mut pb: CvPixelBufferRef = ptr::null_mut();
        let status = unsafe {
            CVPixelBufferCreateWithIOSurface(kCFAllocatorDefault, surface, ptr::null(), &mut pb)
        };
        if status != 0 || pb.is_null() {
            return Err(EncoderError::EncodeFailed {
                vendor: "cv-create-iosurface",
                status: status as i64,
            });
        }
        assert!(!pb.is_null(), "wrap pb non-null after create");
        Ok(pb)
    }
}

impl Drop for VtPixelTransfer {
    fn drop(&mut self) {
        let p = self.session.as_ptr();
        if !p.is_null() {
            unsafe { VTPixelTransferSessionInvalidate(p) };
            unsafe { CFRelease(p) };
        }
    }
}

struct CompletionRing {
    buffer: VecDeque<EncodedBitstream>,
}

impl CompletionRing {
    fn new() -> Self {
        Self {
            buffer: VecDeque::with_capacity(COMPLETION_RING_CAPACITY),
        }
    }

    fn push(&mut self, item: EncodedBitstream) {
        if self.buffer.len() >= COMPLETION_RING_CAPACITY {
            self.buffer.pop_front();
        }
        self.buffer.push_back(item);
        assert!(
            self.buffer.len() <= COMPLETION_RING_CAPACITY,
            "completion ring bounded"
        );
    }

    fn pop(&mut self) -> Option<EncodedBitstream> {
        let item = self.buffer.pop_front();
        assert!(
            self.buffer.len() <= COMPLETION_RING_CAPACITY,
            "completion ring bounded after pop"
        );
        item
    }

    fn len(&self) -> usize {
        let n = self.buffer.len();
        assert!(n <= COMPLETION_RING_CAPACITY, "completion ring len bounded");
        n
    }
}

struct SharedState {
    completed: CompletionRing,
    accepted: u64,
    last_pts_us: u64,
}

struct VtCallbackContext {
    state: Arc<Mutex<SharedState>>,
    failed_completions: AtomicU64,
}

unsafe extern "C" fn vt_compression_output(
    output_callback_refcon: *mut c_void,
    source_frame_refcon: *mut c_void,
    status: OsStatus,
    _info_flags: u32,
    sample_buffer: CmSampleBufferRef,
) {
    if output_callback_refcon.is_null() {
        return;
    }
    let ctx = unsafe { &*(output_callback_refcon as *const VtCallbackContext) };
    if status != NOERR {
        ctx.failed_completions.fetch_add(1, Ordering::Relaxed);
        return;
    }
    if sample_buffer.is_null() {
        return;
    }
    let block = unsafe { CMSampleBufferGetDataBuffer(sample_buffer) };
    if block.is_null() {
        return;
    }
    let len = unsafe { CMBlockBufferGetDataLength(block) };
    if len == 0 || len > MAX_BITSTREAM_BYTES {
        return;
    }
    let mut bytes: Vec<u8> = vec![0u8; len];
    let copy_status =
        unsafe { CMBlockBufferCopyDataBytes(block, 0, len, bytes.as_mut_ptr() as *mut c_void) };
    if copy_status != NOERR {
        return;
    }
    let pts_us = source_frame_refcon as usize as u64;
    let payload =
        match std::panic::catch_unwind(|| EncodedBitstream::new(bytes, pts_us, pts_us, true)) {
            Ok(p) => p,
            Err(_) => return,
        };
    if let Ok(mut guard) = ctx.state.lock() {
        guard.completed.push(payload);
    }
}

struct SlotSurface {
    surface: IoSurfaceRef,
    pixel_buffer: CvPixelBufferRef,
}

pub struct VtCompressionHandoff {
    session: NonNull<c_void>,
    callback_context: Box<VtCallbackContext>,
    shared: Arc<Mutex<SharedState>>,
    surfaces: HashMap<u32, SlotSurface>,
    dims: EncoderDims,
    next_slot: u32,
    frame_interval_us: u64,
    frame_rate: EncoderFrameRate,
    session_rebuilds: u64,
}

unsafe impl Send for VtCompressionHandoff {}

impl VtCompressionHandoff {
    pub fn try_new(dims: EncoderDims) -> Result<Self, EncoderError> {
        Self::try_new_with_frame_rate(dims, EncoderFrameRate::from_fps(30))
    }

    pub fn try_new_with_frame_rate(
        dims: EncoderDims,
        frame_rate: EncoderFrameRate,
    ) -> Result<Self, EncoderError> {
        assert!(
            dims.width > 0 && dims.height > 0,
            "compression dims positive"
        );
        assert!(frame_rate.numerator > 0, "frame rate numerator positive");
        assert!(
            frame_rate.denominator > 0,
            "frame rate denominator positive"
        );
        if dims.width > 7680 || dims.height > 4320 {
            return Err(EncoderError::DimensionsOutOfRange {
                width: dims.width,
                height: dims.height,
            });
        }
        let shared = Arc::new(Mutex::new(SharedState {
            completed: CompletionRing::new(),
            accepted: 0,
            last_pts_us: 0,
        }));
        let mut callback_context = Box::new(VtCallbackContext {
            state: shared.clone(),
            failed_completions: AtomicU64::new(0),
        });
        let cb_ctx_ptr = callback_context.as_mut() as *mut VtCallbackContext as *mut c_void;
        let session = Self::create_session(dims, cb_ctx_ptr, frame_rate)?;
        let handoff = Self {
            session,
            callback_context,
            shared,
            surfaces: HashMap::new(),
            dims,
            next_slot: 0,
            frame_interval_us: frame_rate.frame_interval_us(),
            frame_rate,
            session_rebuilds: 0,
        };
        assert!(
            handoff.session.as_ptr() as usize != 0,
            "session non-null after init"
        );
        assert_eq!(handoff.next_slot, 0, "next slot fresh");
        Ok(handoff)
    }

    fn create_session(
        dims: EncoderDims,
        cb_ctx_ptr: *mut c_void,
        frame_rate: EncoderFrameRate,
    ) -> Result<NonNull<c_void>, EncoderError> {
        assert!(dims.width > 0, "session dims width positive");
        assert!(!cb_ctx_ptr.is_null(), "session callback context non-null");
        assert!(frame_rate.numerator > 0, "frame rate numerator positive");
        let mut raw: VtCompressionSessionRef = ptr::null_mut();
        let status = unsafe {
            VTCompressionSessionCreate(
                kCFAllocatorDefault,
                dims.width as i32,
                dims.height as i32,
                KCM_VIDEO_CODEC_TYPE_H264,
                ptr::null(),
                ptr::null(),
                kCFAllocatorDefault,
                Some(vt_compression_output),
                cb_ctx_ptr,
                &mut raw,
            )
        };
        if status != NOERR || raw.is_null() {
            return Err(EncoderError::SessionInitFailed {
                vendor: "vt-compression",
                status: status as i64,
            });
        }
        let session = NonNull::new(raw).ok_or(EncoderError::SessionInitFailed {
            vendor: "vt-compression",
            status: -1,
        })?;
        Self::configure(session.as_ptr(), frame_rate)?;
        Ok(session)
    }

    fn try_rebuild_session(&mut self) -> bool {
        assert!(
            self.session_rebuilds <= VT_SESSION_REBUILD_MAX,
            "rebuild count within cap"
        );
        if self.session_rebuilds >= VT_SESSION_REBUILD_MAX {
            return false;
        }
        let cb_ctx_ptr = self.callback_context.as_mut() as *mut VtCallbackContext as *mut c_void;
        let Ok(new_session) = Self::create_session(self.dims, cb_ctx_ptr, self.frame_rate) else {
            return false;
        };
        let old = self.session.as_ptr();
        assert!(!old.is_null(), "old session non-null before replace");
        unsafe {
            VTCompressionSessionInvalidate(old);
            CFRelease(old);
        }
        self.session = new_session;
        self.session_rebuilds = self.session_rebuilds.saturating_add(1);
        assert!(
            self.session_rebuilds <= VT_SESSION_REBUILD_MAX,
            "rebuild count stays within cap"
        );
        true
    }

    fn configure(session: *mut c_void, frame_rate: EncoderFrameRate) -> Result<(), EncoderError> {
        assert!(!session.is_null(), "configure session non-null");
        assert!(frame_rate.numerator > 0, "frame rate numerator positive");
        let real_time_true = unsafe { kCFBooleanTrue };
        let st1 = unsafe {
            VTSessionSetProperty(session, kVTCompressionPropertyKey_RealTime, real_time_true)
        };
        if st1 != NOERR {
            return Err(EncoderError::SessionInitFailed {
                vendor: "vt-compression-realtime",
                status: st1 as i64,
            });
        }
        let st2 = unsafe {
            VTSessionSetProperty(
                session,
                kVTCompressionPropertyKey_ProfileLevel,
                kVTProfileLevel_H264_Baseline_AutoLevel,
            )
        };
        if st2 != NOERR {
            return Err(EncoderError::SessionInitFailed {
                vendor: "vt-compression-profile",
                status: st2 as i64,
            });
        }
        let bitrate = cf_num_i32(2_000_000);
        let st3 = unsafe {
            VTSessionSetProperty(session, kVTCompressionPropertyKey_AverageBitRate, bitrate)
        };
        unsafe { CFRelease(bitrate) };
        if st3 != NOERR {
            return Err(EncoderError::SessionInitFailed {
                vendor: "vt-compression-bitrate",
                status: st3 as i64,
            });
        }
        let fps_value = frame_rate.gop_pic_size() as i32;
        let fps = cf_num_i32(fps_value);
        let st4 = unsafe {
            VTSessionSetProperty(session, kVTCompressionPropertyKey_ExpectedFrameRate, fps)
        };
        unsafe { CFRelease(fps) };
        if st4 != NOERR {
            return Err(EncoderError::SessionInitFailed {
                vendor: "vt-compression-fps",
                status: st4 as i64,
            });
        }
        let no_reorder = unsafe { CFRetain(kCFBooleanTrue) };
        let st5 = unsafe {
            VTSessionSetProperty(
                session,
                kVTCompressionPropertyKey_AllowFrameReordering,
                no_reorder,
            )
        };
        unsafe { CFRelease(no_reorder) };
        if st5 != NOERR {
            return Err(EncoderError::SessionInitFailed {
                vendor: "vt-compression-reorder",
                status: st5 as i64,
            });
        }
        Ok(())
    }

    pub fn pending_completion(&self) -> usize {
        let guard = match self.shared.lock() {
            Ok(g) => g,
            Err(_) => return 0,
        };
        let n = guard.completed.len();
        assert!(n <= COMPLETION_RING_CAPACITY, "pending count bounded");
        n
    }

    pub fn accepted_count(&self) -> u64 {
        let guard = match self.shared.lock() {
            Ok(g) => g,
            Err(_) => return 0,
        };
        let n = guard.accepted;
        assert!(
            self.surfaces.len() as u64 <= u32::MAX as u64,
            "surfaces table bounded"
        );
        n
    }

    pub fn failed_completion_count(&self) -> u64 {
        let n = self
            .callback_context
            .failed_completions
            .load(Ordering::Relaxed);
        assert!(
            self.session_rebuilds <= VT_SESSION_REBUILD_MAX,
            "rebuild count within cap"
        );
        n
    }

    pub fn session_rebuild_count(&self) -> u64 {
        let n = self.session_rebuilds;
        assert!(n <= VT_SESSION_REBUILD_MAX, "rebuild count within cap");
        n
    }

    pub fn wait_for_completion(&self) -> Result<(), EncoderError> {
        let until = CmTime {
            value: 0,
            timescale: 0,
            flags: 0,
            epoch: 0,
        };
        let status = unsafe { VTCompressionSessionCompleteFrames(self.session.as_ptr(), until) };
        if status != NOERR {
            return Err(EncoderError::EncodeFailed {
                vendor: "vt-compression-complete",
                status: status as i64,
            });
        }
        Ok(())
    }

    fn encode_frame_once(
        &self,
        pixel_buffer: CvPixelBufferRef,
        pic_params: PicParams,
    ) -> Result<(), EncoderError> {
        assert!(!pixel_buffer.is_null(), "encode pixel buffer non-null");
        assert!(self.frame_interval_us > 0, "frame interval positive");
        let pts = CmTime {
            value: pic_params.pts_us as i64,
            timescale: 1_000_000,
            flags: KCM_TIME_FLAGS_VALID,
            epoch: 0,
        };
        let dur = CmTime {
            value: self.frame_interval_us as i64,
            timescale: 1_000_000,
            flags: KCM_TIME_FLAGS_VALID,
            epoch: 0,
        };
        let mut flags_out: u32 = 0;
        let refcon = pic_params.pts_us as usize as *mut c_void;
        let enc_status = unsafe {
            VTCompressionSessionEncodeFrame(
                self.session.as_ptr(),
                pixel_buffer,
                pts,
                dur,
                ptr::null(),
                refcon,
                &mut flags_out,
            )
        };
        if enc_status != NOERR {
            return Err(EncoderError::EncodeFailed {
                vendor: "vt-compression-encode",
                status: enc_status as i64,
            });
        }
        Ok(())
    }

    fn encode_one(&mut self, slot: HandoffSlot, pic_params: PicParams) -> Result<(), EncoderError> {
        assert!(slot.shared_handle != 0, "encode slot handle non-zero");
        let pixel_buffer = match self.surfaces.get(&slot.slot_index) {
            Some(entry) => {
                assert!(!entry.surface.is_null(), "cached slot surface non-null");
                assert!(
                    !entry.pixel_buffer.is_null(),
                    "cached pixel buffer non-null"
                );
                entry.pixel_buffer
            }
            None => {
                return Err(EncoderError::SlotUnknown {
                    slot_index: slot.slot_index,
                });
            }
        };
        let mut attempts: usize = 0;
        while attempts < VT_ENCODE_ATTEMPTS_PER_FRAME_MAX {
            attempts += 1;
            assert!(
                attempts <= VT_ENCODE_ATTEMPTS_PER_FRAME_MAX,
                "encode attempts bounded"
            );
            match self.encode_frame_once(pixel_buffer, pic_params) {
                Ok(()) => {
                    if let Ok(mut guard) = self.shared.lock() {
                        guard.accepted = guard.accepted.saturating_add(1);
                        guard.last_pts_us = pic_params.pts_us;
                    }
                    return Ok(());
                }
                Err(err) => {
                    if !is_invalid_session_error(&err) {
                        return Err(err);
                    }
                    if !self.try_rebuild_session() {
                        break;
                    }
                }
            }
        }
        Err(EncoderError::EncodeFailed {
            vendor: "vt-compression-invalid-session",
            status: KVT_INVALID_SESSION_ERR as i64,
        })
    }
}

impl Drop for VtCompressionHandoff {
    fn drop(&mut self) {
        for (_, entry) in self.surfaces.drain() {
            if !entry.pixel_buffer.is_null() {
                unsafe { CVPixelBufferRelease(entry.pixel_buffer) };
            }
        }
        let p = self.session.as_ptr();
        if !p.is_null() {
            unsafe { VTCompressionSessionInvalidate(p) };
            unsafe { CFRelease(p) };
        }
        let _ = &self.callback_context;
    }
}

impl VideoToolboxHandoff for VtCompressionHandoff {
    fn register_slot(
        &mut self,
        iosurface_handle: u64,
        _key: u64,
        dims: EncoderDims,
    ) -> Result<HandoffSlot, EncoderError> {
        if iosurface_handle == 0 {
            return Err(EncoderError::SlotUnknown {
                slot_index: u32::MAX,
            });
        }
        if dims.width == 0 || dims.height == 0 {
            return Err(EncoderError::DimensionsOutOfRange {
                width: dims.width,
                height: dims.height,
            });
        }
        let idx = self.next_slot;
        let surface = iosurface_handle as IoSurfaceRef;
        if surface.is_null() {
            return Err(EncoderError::SlotUnknown { slot_index: idx });
        }
        let mut pixel_buffer: CvPixelBufferRef = ptr::null_mut();
        let status = unsafe {
            CVPixelBufferCreateWithIOSurface(
                kCFAllocatorDefault,
                surface,
                ptr::null(),
                &mut pixel_buffer,
            )
        };
        if status != 0 || pixel_buffer.is_null() {
            return Err(EncoderError::RegisterFailed {
                vendor: "vt-cv-create",
                status: status as i64,
            });
        }
        self.surfaces.insert(
            idx,
            SlotSurface {
                surface,
                pixel_buffer,
            },
        );
        self.next_slot = self.next_slot.saturating_add(1);
        let slot = HandoffSlot::new(idx, iosurface_handle);
        assert_eq!(
            slot.shared_handle, iosurface_handle,
            "slot handle preserved"
        );
        assert!(self.next_slot > idx, "slot counter advanced");
        Ok(slot)
    }

    fn encode_shared_async(
        &mut self,
        slot: HandoffSlot,
        _key: u64,
        dims: EncoderDims,
        pic_params: PicParams,
    ) -> Result<(), EncoderError> {
        if dims.width == 0 || dims.height == 0 {
            return Err(EncoderError::DimensionsOutOfRange {
                width: dims.width,
                height: dims.height,
            });
        }
        self.encode_one(slot, pic_params)
    }

    fn poll_completed(&mut self, _slot: HandoffSlot) -> Option<EncodedBitstream> {
        let mut guard = self.shared.lock().ok()?;
        let item = guard.completed.pop();
        if let Some(ref payload) = item {
            assert!(!payload.data.is_empty(), "polled payload non-empty");
            assert!(
                payload.data.len() <= MAX_BITSTREAM_BYTES,
                "polled payload bounded"
            );
        }
        item
    }

    fn unregister_slot(&mut self, slot: HandoffSlot) {
        assert!(slot.shared_handle != 0, "unregister handle non-zero");
        if let Some(entry) = self.surfaces.remove(&slot.slot_index) {
            assert!(
                !entry.pixel_buffer.is_null(),
                "cached pixel buffer non-null on unregister"
            );
            unsafe { CVPixelBufferRelease(entry.pixel_buffer) };
        }
    }

    fn encode_shared(
        &mut self,
        submission: EncoderSubmission,
        callback: &mut dyn crate::encoder_handoff::EncoderCompletionCallback,
    ) -> Result<(), RingError> {
        if submission.shared_handle == 0 {
            return Err(RingError::UnknownSlot);
        }
        if submission.dims.width == 0 || submission.dims.height == 0 {
            return Err(RingError::BackendFailed {
                source: crate::backend::BackendError::DimensionsOutOfRange {
                    width: submission.dims.width,
                    height: submission.dims.height,
                },
            });
        }
        let slot = HandoffSlot::new(
            (submission.sequence & 0x3f) as u32,
            submission.shared_handle,
        );
        let pts_us = match submission.capture_pts_us {
            Some(capture_pts_us) => capture_pts_us,
            None => submission.sequence.saturating_mul(self.frame_interval_us),
        };
        let params = PicParams::new(pts_us, false);
        let encoded_bytes_estimate = self.pending_completion() as u32;
        if let Err(e) = self.encode_one(slot, params) {
            return Err(RingError::BackendFailed {
                source: crate::backend::BackendError::PlatformUnsupported {
                    reason: match e {
                        EncoderError::SlotUnknown { .. } => "vt slot unknown",
                        EncoderError::EncodeFailed { .. } => "vt encode failed",
                        _ => "vt session error",
                    },
                },
            });
        }
        callback.on_complete(submission.sequence, encoded_bytes_estimate);
        Ok(())
    }
}

#[cfg(test)]
pub(crate) fn make_cv_nv12_pixel_buffer(
    width: u32,
    height: u32,
) -> objc2_core_foundation::CFRetained<objc2_core_video::CVPixelBuffer> {
    use core::ptr::NonNull;
    use objc2_core_foundation::{CFDictionary, CFRetained};
    use objc2_core_video::CVPixelBuffer;

    let mut empty_keys: [*const c_void; 0] = [];
    let mut empty_vals: [*const c_void; 0] = [];
    let iosurf_dict: CFRetained<CFDictionary> = unsafe {
        CFDictionary::new(
            None,
            empty_keys.as_mut_ptr(),
            empty_vals.as_mut_ptr(),
            0,
            &objc2_core_foundation::kCFTypeDictionaryKeyCallBacks,
            &objc2_core_foundation::kCFTypeDictionaryValueCallBacks,
        )
        .expect("iosurf empty dict")
    };
    let key_ref: &objc2_core_foundation::CFString =
        unsafe { objc2_core_video::kCVPixelBufferIOSurfacePropertiesKey };
    let key_ptr: *const c_void = key_ref as *const _ as *const c_void;
    let val_ptr: *const c_void = &*iosurf_dict as *const _ as *const c_void;
    let mut keys = [key_ptr];
    let mut vals = [val_ptr];
    let attrs: CFRetained<CFDictionary> = unsafe {
        CFDictionary::new(
            None,
            keys.as_mut_ptr(),
            vals.as_mut_ptr(),
            1,
            &objc2_core_foundation::kCFTypeDictionaryKeyCallBacks,
            &objc2_core_foundation::kCFTypeDictionaryValueCallBacks,
        )
        .expect("attrs dict")
    };
    let mut out: *mut CVPixelBuffer = std::ptr::null_mut();
    let status = unsafe {
        objc2_core_video::CVPixelBufferCreate(
            None,
            width as usize,
            height as usize,
            KCV_PIXEL_FORMAT_TYPE_420_YPCBCR8_BIPLANAR_VIDEO,
            Some(&attrs),
            NonNull::new(&mut out).expect("out pointer non-null"),
        )
    };
    assert_eq!(status, 0, "CVPixelBufferCreate succeeded");
    assert!(!out.is_null(), "CVPixelBufferCreate produced buffer");
    unsafe { CFRetained::from_raw(NonNull::new_unchecked(out)) }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn make_handoff() -> VtCompressionHandoff {
        VtCompressionHandoff::try_new(EncoderDims::new(1280, 720)).expect("create handoff")
    }

    pub(super) fn iosurface_ptr_from_pb(pb: &objc2_core_video::CVPixelBuffer) -> *mut c_void {
        let s = objc2_core_video::CVPixelBufferGetIOSurface(Some(pb));
        let surface = s.expect("pixel buffer must be IOSurface-backed");
        let raw: *const objc2_io_surface::IOSurfaceRef = &*surface;
        raw as *mut c_void
    }

    #[test]
    fn vt_compression_handoff_encodes_one_frame() {
        let mut handoff = make_handoff();
        let pb = make_cv_nv12_pixel_buffer(1280, 720);
        let surface = iosurface_ptr_from_pb(&pb);
        let slot = handoff
            .register_slot(surface as u64, 0, EncoderDims::new(1280, 720))
            .expect("register slot");
        let params = PicParams::new(0, false);
        handoff
            .encode_shared_async(slot, 0, EncoderDims::new(1280, 720), params)
            .expect("encode async");
        handoff.wait_for_completion().expect("complete frames");
        let payload = handoff.poll_completed(slot).expect("polled bitstream");
        assert!(!payload.data.is_empty(), "encoded payload non-empty");
        assert!(
            payload.data.len() <= MAX_BITSTREAM_BYTES,
            "encoded payload bounded"
        );
    }

    struct RecordingCallback {
        seen: Vec<(u64, u32)>,
    }

    impl crate::encoder_handoff::EncoderCompletionCallback for RecordingCallback {
        fn on_complete(&mut self, sequence: u64, encoded_bytes: u32) {
            self.seen.push((sequence, encoded_bytes));
        }
    }

    #[test]
    fn output_callback_counts_failed_completions() {
        let ctx = VtCallbackContext {
            state: Arc::new(Mutex::new(SharedState {
                completed: CompletionRing::new(),
                accepted: 0,
                last_pts_us: 0,
            })),
            failed_completions: AtomicU64::new(0),
        };
        let ctx_ptr = &ctx as *const VtCallbackContext as *mut c_void;
        unsafe {
            vt_compression_output(
                ctx_ptr,
                ptr::null_mut(),
                KVT_INVALID_SESSION_ERR,
                0,
                ptr::null_mut(),
            );
            vt_compression_output(ctx_ptr, ptr::null_mut(), -1, 0, ptr::null_mut());
        }
        assert_eq!(ctx.failed_completions.load(Ordering::Relaxed), 2);
        let guard = ctx.state.lock().expect("state lock");
        assert_eq!(
            guard.completed.len(),
            0,
            "failed completions enqueue nothing"
        );
    }

    #[test]
    fn failed_completion_count_starts_at_zero_and_survives_encode() {
        let mut handoff = make_handoff();
        assert_eq!(handoff.failed_completion_count(), 0);
        let pb = make_cv_nv12_pixel_buffer(1280, 720);
        let surface = iosurface_ptr_from_pb(&pb);
        let slot = handoff
            .register_slot(surface as u64, 0, EncoderDims::new(1280, 720))
            .expect("register slot");
        handoff
            .encode_shared_async(
                slot,
                0,
                EncoderDims::new(1280, 720),
                PicParams::new(0, false),
            )
            .expect("encode async");
        handoff.wait_for_completion().expect("complete frames");
        assert_eq!(handoff.failed_completion_count(), 0);
    }

    #[test]
    fn session_rebuild_bounded_by_named_cap() {
        let mut handoff = make_handoff();
        assert_eq!(handoff.session_rebuild_count(), 0);
        for expected in 1..=VT_SESSION_REBUILD_MAX {
            assert!(handoff.try_rebuild_session(), "rebuild within cap succeeds");
            assert_eq!(handoff.session_rebuild_count(), expected);
        }
        assert!(
            !handoff.try_rebuild_session(),
            "rebuild beyond cap rejected"
        );
        assert_eq!(handoff.session_rebuild_count(), VT_SESSION_REBUILD_MAX);
    }

    #[test]
    fn session_still_encodes_after_rebuild() {
        let mut handoff = make_handoff();
        assert!(handoff.try_rebuild_session(), "first rebuild succeeds");
        let pb = make_cv_nv12_pixel_buffer(1280, 720);
        let surface = iosurface_ptr_from_pb(&pb);
        let slot = handoff
            .register_slot(surface as u64, 0, EncoderDims::new(1280, 720))
            .expect("register slot");
        handoff
            .encode_shared_async(
                slot,
                0,
                EncoderDims::new(1280, 720),
                PicParams::new(0, false),
            )
            .expect("encode async after rebuild");
        handoff.wait_for_completion().expect("complete frames");
        let payload = handoff.poll_completed(slot).expect("polled bitstream");
        assert!(!payload.data.is_empty(), "encoded payload non-empty");
        assert_eq!(handoff.session_rebuild_count(), 1);
    }

    #[test]
    fn encode_shared_uses_capture_pts_when_present() {
        let mut handoff = make_handoff();
        let pb = make_cv_nv12_pixel_buffer(1280, 720);
        let surface = iosurface_ptr_from_pb(&pb);
        let slot = handoff
            .register_slot(surface as u64, 0, EncoderDims::new(1280, 720))
            .expect("register slot");
        assert_eq!(slot.slot_index, 0);
        let dims = EncoderDims::new(1280, 720);
        let submission =
            EncoderSubmission::new(surface as u64, 0, dims, 0).with_capture_pts_us(987_654);
        let mut cb = RecordingCallback { seen: Vec::new() };
        VideoToolboxHandoff::encode_shared(&mut handoff, submission, &mut cb)
            .expect("encode shared with capture pts");
        handoff.wait_for_completion().expect("complete frames");
        let payload = handoff.poll_completed(slot).expect("polled bitstream");
        assert_eq!(payload.pts_us, 987_654, "real capture pts threaded through");
        assert_eq!(cb.seen.len(), 1);
    }

    #[test]
    fn encode_shared_synthesizes_pts_when_capture_pts_absent() {
        let mut handoff = make_handoff();
        let pb = make_cv_nv12_pixel_buffer(1280, 720);
        let surface = iosurface_ptr_from_pb(&pb);
        let slot = handoff
            .register_slot(surface as u64, 0, EncoderDims::new(1280, 720))
            .expect("register slot");
        assert_eq!(slot.slot_index, 0);
        let dims = EncoderDims::new(1280, 720);
        let submission = EncoderSubmission::new(surface as u64, 0, dims, 0);
        assert_eq!(submission.capture_pts_us, None);
        let mut cb = RecordingCallback { seen: Vec::new() };
        VideoToolboxHandoff::encode_shared(&mut handoff, submission, &mut cb)
            .expect("encode shared without capture pts");
        handoff.wait_for_completion().expect("complete frames");
        let payload = handoff.poll_completed(slot).expect("polled bitstream");
        assert_eq!(payload.pts_us, 0, "sequence 0 synthesizes pts 0");
    }

    #[test]
    fn invalid_session_error_detection_is_exact() {
        let invalid = EncoderError::EncodeFailed {
            vendor: "vt-compression-encode",
            status: KVT_INVALID_SESSION_ERR as i64,
        };
        assert!(is_invalid_session_error(&invalid));
        let other_status = EncoderError::EncodeFailed {
            vendor: "vt-compression-encode",
            status: -1,
        };
        assert!(!is_invalid_session_error(&other_status));
        let other_vendor = EncoderError::EncodeFailed {
            vendor: "vt-cv-create",
            status: KVT_INVALID_SESSION_ERR as i64,
        };
        assert!(!is_invalid_session_error(&other_vendor));
    }

    #[test]
    fn vt_compression_handoff_handles_back_pressure() {
        let mut handoff = make_handoff();
        let pb = make_cv_nv12_pixel_buffer(1280, 720);
        let surface = iosurface_ptr_from_pb(&pb);
        let slot = handoff
            .register_slot(surface as u64, 0, EncoderDims::new(1280, 720))
            .expect("register slot");
        let total: u64 = (COMPLETION_RING_CAPACITY as u64) + 8;
        for i in 0..total {
            let params = PicParams::new(i * 33_333, false);
            handoff
                .encode_shared_async(slot, 0, EncoderDims::new(1280, 720), params)
                .expect("encode async");
        }
        handoff.wait_for_completion().expect("complete frames");
        let pending = handoff.pending_completion();
        assert!(
            pending <= COMPLETION_RING_CAPACITY,
            "completion ring stays bounded"
        );
        let mut drained = 0usize;
        while handoff.poll_completed(slot).is_some() {
            drained += 1;
            if drained > COMPLETION_RING_CAPACITY * 2 {
                break;
            }
        }
        assert!(
            drained <= COMPLETION_RING_CAPACITY,
            "drained respects completion bound"
        );
    }
}
