#[cfg(target_os = "windows")]
pub mod locked {
  use core::ffi::c_void;
  use std::io::Write;
  use windows::core::{Error, Result};
  use windows::Win32::Foundation::HANDLE;
  use windows::Win32::System::StationsAndDesktops::{
    CloseDesktop, GetUserObjectInformationW, OpenInputDesktop, DESKTOP_ACCESS_FLAGS,
    DESKTOP_CONTROL_FLAGS, DESKTOP_READOBJECTS, DESKTOP_SWITCHDESKTOP, HDESK, UOI_NAME,
  };

  /// Returns true if the input desktop is "Winlogon" (session locked).
  pub fn is_session_locked() -> Result<bool> {
    unsafe {
      // dwFlags must be DESKTOP_CONTROL_FLAGS.
      let hdesk: HDESK = OpenInputDesktop(
        DESKTOP_CONTROL_FLAGS(0),
        false,
        // Combine access flags via inner u32s (BitOr isn’t implemented on the wrapper).
        DESKTOP_ACCESS_FLAGS(DESKTOP_READOBJECTS.0 | DESKTOP_SWITCHDESKTOP.0),
      )?;

      // Ask how many bytes are needed for the desktop name.
      let mut needed: u32 = 0;
      // Convert HDESK -> HANDLE for GetUserObjectInformationW.
      let _ = GetUserObjectInformationW(HANDLE(hdesk.0), UOI_NAME, None, 0, Some(&mut needed));

      if needed == 0 {
        let _ = CloseDesktop(hdesk);
        return Err(Error::from_win32());
      }

      // Fetch the name.
      let mut buf: Vec<u16> = vec![0; (needed as usize + 1) / 2];
      let result = GetUserObjectInformationW(
        HANDLE(hdesk.0),
        UOI_NAME,
        Some(buf.as_mut_ptr() as *mut c_void),
        needed,
        Some(&mut needed),
      );

      let _ = CloseDesktop(hdesk);
      if result.is_err() {
        return Err(Error::from_win32());
      }

      // Convert to String and compare.
      let len = buf.iter().position(|&c| c == 0).unwrap_or(buf.len());
      let name = String::from_utf16_lossy(&buf[..len]);

      Ok(name.eq_ignore_ascii_case("Winlogon"))
    }
  }

  #[napi]
  pub fn session_locked() -> bool {
    match is_session_locked() {
      Ok(d) => {
        d
      }
      Err(err) => {
        true
      }
    }
  }
}

#[cfg(not(target_os = "windows"))]
pub mod locked {
  use core_foundation::base::{CFGetTypeID, TCFType};
  use core_foundation::boolean::{CFBoolean, CFBooleanGetTypeID};
  use core_foundation::dictionary::CFDictionaryRef;
  use core_foundation::string::CFString;

  #[link(name = "ApplicationServices", kind = "framework")]
  extern "C" {
    fn CGSessionCopyCurrentDictionary() -> CFDictionaryRef;
  }

  #[napi]
  pub fn session_locked() -> bool {
    unsafe {
      let dict_ref = CGSessionCopyCurrentDictionary();
      if dict_ref.is_null() {
        return false;
      }

      let dict = core_foundation::dictionary::CFDictionary::<
        CFString,
        core_foundation::base::CFTypeRef,
      >::wrap_under_create_rule(dict_ref);

      let key = CFString::from_static_string("CGSSessionScreenIsLocked");

      if let Some(value_ref) = dict.find(&key) {
        // value_ref: CFTypeRef (*const c_void). Check its runtime type first.
        if CFGetTypeID(*value_ref) == CFBooleanGetTypeID() {
          let b = CFBoolean::wrap_under_get_rule(*value_ref as *const _);
          return b.into();
        }
      }

      false
    }
  }
}
