//! Windows VFS implementation.
//!
//! This backend provides the same `Vfs` / `VfsFile` surface as `UnixVfs`,
//! using Windows-friendly file APIs and lock sidecars backed by OS advisory
//! locks (`LockFileEx` via `advisory-lock`) that mirror SQLite lock-level
//! transitions (`NONE` → `SHARED` → `RESERVED` → `PENDING` → `EXCLUSIVE`).

use std::collections::HashMap;
use std::env;
use std::ffi::OsString;
use std::fs::{self, File, OpenOptions};
use std::os::windows::fs::{FileExt, OpenOptionsExt};
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicU64, Ordering, fence};
use std::sync::{Arc, Mutex, OnceLock};

use advisory_lock::{AdvisoryFileLock, FileLockError, FileLockMode};
use fsqlite_error::{FrankenError, Result};
use fsqlite_types::LockLevel;
use fsqlite_types::cx::Cx;
use fsqlite_types::flags::{AccessFlags, SyncFlags, VfsOpenFlags};
use tracing::{debug, info};

use crate::shm::{
    SQLITE_SHM_EXCLUSIVE, SQLITE_SHM_LOCK, SQLITE_SHM_SHARED, SQLITE_SHM_UNLOCK, ShmRegion,
    WAL_TOTAL_LOCKS,
};
use crate::traits::{Vfs, VfsFile};

/// SQLite I/O capability bit indicating files cannot be deleted while open.
const SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN: u32 = 0x0000_0800;
const WINDOWS_FILE_SHARE_READ: u32 = 0x0000_0001;
const WINDOWS_FILE_SHARE_WRITE: u32 = 0x0000_0002;
const WINDOWS_SHARE_READ_WRITE: u32 = WINDOWS_FILE_SHARE_READ | WINDOWS_FILE_SHARE_WRITE;

fn checkpoint_or_abort(cx: &Cx) -> Result<()> {
    cx.checkpoint().map_err(|_| FrankenError::Abort)
}

fn lock_poisoned(name: &str) -> FrankenError {
    FrankenError::internal(format!("{name} lock poisoned"))
}

fn windows_open_options() -> OpenOptions {
    let mut options = OpenOptions::new();
    options.share_mode(WINDOWS_SHARE_READ_WRITE);
    options
}

fn resolve_path(path: &Path) -> Result<PathBuf> {
    if path.is_absolute() {
        Ok(path.to_path_buf())
    } else {
        Ok(env::current_dir()?.join(path))
    }
}

fn sqlite_shm_path(path: &Path) -> PathBuf {
    let mut shm: OsString = path.as_os_str().to_owned();
    shm.push("-shm");
    PathBuf::from(shm)
}

fn sqlite_shared_lock_path(path: &Path) -> PathBuf {
    let mut p: OsString = path.as_os_str().to_owned();
    p.push("-lock-shared");
    PathBuf::from(p)
}

fn sqlite_reserved_lock_path(path: &Path) -> PathBuf {
    let mut p: OsString = path.as_os_str().to_owned();
    p.push("-lock-reserved");
    PathBuf::from(p)
}

fn sqlite_pending_lock_path(path: &Path) -> PathBuf {
    let mut p: OsString = path.as_os_str().to_owned();
    p.push("-lock-pending");
    PathBuf::from(p)
}

// The three advisory-lock sidecars `WindowsOsLockFiles::open` writes next to
// every DB it touches. Returned as an array so callers can iterate uniformly.
fn windows_lock_sidecar_paths(path: &Path) -> [PathBuf; 3] {
    [
        sqlite_shared_lock_path(path),
        sqlite_reserved_lock_path(path),
        sqlite_pending_lock_path(path),
    ]
}

// Best-effort removal of the three advisory-lock sidecars alongside `path`.
// Errors are intentionally swallowed: sidecars are advisory and may be missing,
// in use by a racing handle, or already cleaned up. Without this, every
// transient DB file (e.g. VACUUM INTO backups) leaks three zero-byte files,
// and a downstream caller that re-enumerates the dir can mistake an orphan
// sidecar for a backup root and chain a fresh set on top.
fn try_remove_windows_lock_sidecars(path: &Path) {
    for sidecar in windows_lock_sidecar_paths(path) {
        let _ = fs::remove_file(sidecar);
    }
}

fn ensure_shm_file_len(path: &Path, min_len: u64) -> Result<()> {
    let mut options = windows_open_options();
    let file = options
        .read(true)
        .write(true)
        .create(true)
        .truncate(false)
        .open(path)?;
    let current = file.metadata()?.len();
    if current < min_len {
        file.set_len(min_len)?;
    }
    Ok(())
}

fn open_windows_lock_sidecar(path: &Path) -> Result<(File, bool)> {
    loop {
        let mut create_options = windows_open_options();
        match create_options
            .read(true)
            .write(true)
            .create_new(true)
            .open(path)
        {
            Ok(file) => return Ok((file, true)),
            Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {
                let mut open_options = windows_open_options();
                match open_options.read(true).write(true).open(path) {
                    Ok(file) => return Ok((file, false)),
                    Err(err) if err.kind() == std::io::ErrorKind::NotFound => {}
                    Err(err) => return Err(FrankenError::Io(err)),
                }
            }
            Err(err) => return Err(FrankenError::Io(err)),
        }
    }
}

#[derive(Debug, Default)]
struct WindowsVfsInner {
    next_temp_id: u64,
}

/// Windows filesystem-backed VFS implementation.
#[derive(Debug, Clone, Default)]
pub struct WindowsVfs {
    inner: Arc<Mutex<WindowsVfsInner>>,
}

impl WindowsVfs {
    /// Create a new Windows VFS instance.
    #[must_use]
    pub fn new() -> Self {
        info!(
            target: "fsqlite_vfs::windows",
            sector_size = 4096_u32,
            "windows vfs initialized"
        );
        Self::default()
    }

    fn next_temp_path(&self) -> Result<PathBuf> {
        let mut inner = self
            .inner
            .lock()
            .map_err(|_| lock_poisoned("windows vfs inner"))?;
        let id = inner.next_temp_id.max(next_temp_id());
        inner.next_temp_id = id
            .checked_add(1)
            .ok_or_else(|| FrankenError::internal("temp file id overflow"))?;
        Ok(env::temp_dir().join(format!("fsqlite-windows-{id}.tmp")))
    }
}

#[derive(Debug, Clone, Default)]
struct ShmSlotState {
    shared_holders: HashMap<u64, u32>,
    exclusive_owner: Option<u64>,
}

#[derive(Debug)]
struct WindowsShmState {
    regions: HashMap<u32, ShmRegion>,
    slots: Vec<ShmSlotState>,
    owner_refs: HashMap<u64, u32>,
}

impl Default for WindowsShmState {
    fn default() -> Self {
        let slot_count = usize::try_from(WAL_TOTAL_LOCKS).expect("WAL_TOTAL_LOCKS must fit usize");
        Self {
            regions: HashMap::new(),
            slots: vec![ShmSlotState::default(); slot_count],
            owner_refs: HashMap::new(),
        }
    }
}

#[derive(Debug)]
struct WindowsShmTable {
    map: Mutex<HashMap<PathBuf, Arc<Mutex<WindowsShmState>>>>,
}

impl WindowsShmTable {
    fn new() -> Self {
        Self {
            map: Mutex::new(HashMap::new()),
        }
    }

    fn get(&self, path: &Path) -> Result<Option<Arc<Mutex<WindowsShmState>>>> {
        let map = self
            .map
            .lock()
            .map_err(|_| lock_poisoned("windows shm table"))?;
        Ok(map.get(path).map(Arc::clone))
    }

    fn get_or_create(&self, path: &Path) -> Result<Arc<Mutex<WindowsShmState>>> {
        let mut map = self
            .map
            .lock()
            .map_err(|_| lock_poisoned("windows shm table"))?;
        Ok(Arc::clone(map.entry(path.to_path_buf()).or_insert_with(
            || Arc::new(Mutex::new(WindowsShmState::default())),
        )))
    }

    fn remove_if_orphaned(&self, path: &Path) -> Result<()> {
        let mut map = self
            .map
            .lock()
            .map_err(|_| lock_poisoned("windows shm table"))?;
        if let Some(state) = map.get(path) {
            let orphaned = state
                .lock()
                .map_err(|_| lock_poisoned("windows shm state"))?
                .owner_refs
                .is_empty();
            if orphaned {
                map.remove(path);
            }
        }
        Ok(())
    }
}

fn windows_shm_table() -> &'static WindowsShmTable {
    static TABLE: OnceLock<WindowsShmTable> = OnceLock::new();
    TABLE.get_or_init(WindowsShmTable::new)
}

fn next_owner_id() -> u64 {
    static OWNER_SEQ: AtomicU64 = AtomicU64::new(1);
    OWNER_SEQ.fetch_add(1, Ordering::Relaxed)
}

fn next_temp_id() -> u64 {
    static TEMP_SEQ: AtomicU64 = AtomicU64::new(1);
    TEMP_SEQ.fetch_add(1, Ordering::Relaxed)
}

fn to_slot_index(slot: u32) -> Result<usize> {
    usize::try_from(slot).map_err(|_| FrankenError::OutOfRange {
        what: "shm slot index".to_string(),
        value: slot.to_string(),
    })
}

fn next_lock_level(level: LockLevel) -> Option<LockLevel> {
    match level {
        LockLevel::None => Some(LockLevel::Shared),
        LockLevel::Shared => Some(LockLevel::Reserved),
        LockLevel::Reserved => Some(LockLevel::Pending),
        LockLevel::Pending => Some(LockLevel::Exclusive),
        LockLevel::Exclusive => None,
    }
}

fn lock_level_slot(level: LockLevel) -> Option<usize> {
    match level {
        LockLevel::None => None,
        LockLevel::Shared => Some(0),
        LockLevel::Reserved => Some(1),
        LockLevel::Pending => Some(2),
        LockLevel::Exclusive => Some(3),
    }
}

#[derive(Debug)]
struct WindowsOsLockFiles {
    shared_file: File,
    reserved_file: File,
    pending_file: File,
    held_levels: [bool; 4],
}

impl WindowsOsLockFiles {
    fn open(path: &Path) -> Result<Self> {
        let shared_path = sqlite_shared_lock_path(path);
        let reserved_path = sqlite_reserved_lock_path(path);
        let pending_path = sqlite_pending_lock_path(path);
        let (shared_file, shared_created) = open_windows_lock_sidecar(&shared_path)?;
        let (reserved_file, reserved_created) = match open_windows_lock_sidecar(&reserved_path) {
            Ok(opened) => opened,
            Err(err) => {
                drop(shared_file);
                if shared_created {
                    let _ = fs::remove_file(&shared_path);
                }
                return Err(err);
            }
        };
        let (pending_file, _) = match open_windows_lock_sidecar(&pending_path) {
            Ok(opened) => opened,
            Err(err) => {
                drop(reserved_file);
                drop(shared_file);
                if reserved_created {
                    let _ = fs::remove_file(&reserved_path);
                }
                if shared_created {
                    let _ = fs::remove_file(&shared_path);
                }
                return Err(err);
            }
        };
        Ok(Self {
            shared_file,
            reserved_file,
            pending_file,
            held_levels: [false; 4],
        })
    }

    fn try_lock_shared(file: &File) -> Result<()> {
        match AdvisoryFileLock::try_lock(file, FileLockMode::Shared) {
            Ok(()) => Ok(()),
            Err(FileLockError::AlreadyLocked) => Err(FrankenError::Busy),
            Err(FileLockError::Io(err)) => Err(FrankenError::Io(err)),
        }
    }

    fn try_lock_exclusive(file: &File) -> Result<()> {
        match AdvisoryFileLock::try_lock(file, FileLockMode::Exclusive) {
            Ok(()) => Ok(()),
            Err(FileLockError::AlreadyLocked) => Err(FrankenError::Busy),
            Err(FileLockError::Io(err)) => Err(FrankenError::Io(err)),
        }
    }

    fn unlock_file(file: &File) -> Result<()> {
        match AdvisoryFileLock::unlock(file) {
            Ok(()) => Ok(()),
            Err(FileLockError::AlreadyLocked) => Err(FrankenError::LockFailed {
                detail: "unlock called for contended lock".to_string(),
            }),
            Err(FileLockError::Io(err)) => Err(FrankenError::Io(err)),
        }
    }

    fn lock_file_for_level(&self, level: LockLevel) -> Option<&File> {
        match level {
            LockLevel::None => None,
            LockLevel::Shared | LockLevel::Exclusive => Some(&self.shared_file),
            LockLevel::Reserved => Some(&self.reserved_file),
            LockLevel::Pending => Some(&self.pending_file),
        }
    }

    fn lock_held(&self, level: LockLevel) -> bool {
        lock_level_slot(level).is_some_and(|slot| self.held_levels[slot])
    }

    fn set_lock_held(&mut self, level: LockLevel, held: bool) {
        if let Some(slot) = lock_level_slot(level) {
            self.held_levels[slot] = held;
        }
    }

    fn try_lock_level(&mut self, level: LockLevel) -> Result<()> {
        if level == LockLevel::None {
            return Ok(());
        }

        if self.lock_held(level) {
            return Ok(());
        }

        if level == LockLevel::Shared {
            // Match SQLite's pending-byte protocol: readers briefly take a
            // shared lock on the pending sidecar before acquiring the shared
            // range. A pending writer holds this sidecar exclusively, blocking
            // new readers while existing readers drain.
            Self::try_lock_shared(&self.pending_file)?;
            let shared_result = Self::try_lock_shared(&self.shared_file);
            let pending_unlock = Self::unlock_file(&self.pending_file);
            if let Err(err) = shared_result {
                pending_unlock?;
                return Err(err);
            }
            if let Err(err) = pending_unlock {
                let _ = Self::unlock_file(&self.shared_file);
                return Err(err);
            }
            self.set_lock_held(LockLevel::Shared, true);
            return Ok(());
        }

        if level == LockLevel::Exclusive {
            // EXCLUSIVE conflicts with SHARED by upgrading the same shared
            // sidecar from shared to exclusive. Locking a separate
            // "exclusive" sidecar would only exclude other writers and would
            // allow readers through.
            let had_shared = self.lock_held(LockLevel::Shared);
            if had_shared {
                Self::unlock_file(&self.shared_file)?;
                self.set_lock_held(LockLevel::Shared, false);
            }
            if let Err(err) = Self::try_lock_exclusive(&self.shared_file) {
                if had_shared && Self::try_lock_shared(&self.shared_file).is_ok() {
                    self.set_lock_held(LockLevel::Shared, true);
                }
                return Err(err);
            }
            self.set_lock_held(LockLevel::Exclusive, true);
            return Ok(());
        }

        let file = self
            .lock_file_for_level(level)
            .ok_or_else(|| FrankenError::internal("invalid lock level"))?;
        Self::try_lock_exclusive(file)?;
        self.set_lock_held(level, true);
        Ok(())
    }

    fn unlock_to(&mut self, level: LockLevel) -> Result<()> {
        if self.lock_held(LockLevel::Exclusive) && level < LockLevel::Exclusive {
            Self::unlock_file(&self.shared_file)?;
            self.set_lock_held(LockLevel::Exclusive, false);
            if level >= LockLevel::Shared {
                Self::try_lock_shared(&self.shared_file)?;
                self.set_lock_held(LockLevel::Shared, true);
            }
        }

        for held_level in [LockLevel::Pending, LockLevel::Reserved, LockLevel::Shared] {
            if level < held_level && self.lock_held(held_level) {
                let file = self
                    .lock_file_for_level(held_level)
                    .ok_or_else(|| FrankenError::internal("invalid lock level"))?;
                Self::unlock_file(file)?;
                self.set_lock_held(held_level, false);
            }
        }
        Ok(())
    }

    fn highest_held_level(&self) -> LockLevel {
        [
            LockLevel::Exclusive,
            LockLevel::Pending,
            LockLevel::Reserved,
            LockLevel::Shared,
        ]
        .into_iter()
        .find(|level| self.lock_held(*level))
        .unwrap_or(LockLevel::None)
    }

    fn reserved_locked_by_other(&self) -> Result<bool> {
        if self.lock_held(LockLevel::Reserved) {
            return Ok(false);
        }

        match AdvisoryFileLock::try_lock(&self.reserved_file, FileLockMode::Exclusive) {
            Ok(()) => {
                Self::unlock_file(&self.reserved_file)?;
                Ok(false)
            }
            Err(FileLockError::AlreadyLocked) => Ok(true),
            Err(FileLockError::Io(err)) => Err(FrankenError::Io(err)),
        }
    }
}

impl Vfs for WindowsVfs {
    type File = WindowsFile;

    fn name(&self) -> &'static str {
        "windows"
    }

    #[allow(clippy::significant_drop_tightening)]
    fn open(
        &self,
        cx: &Cx,
        path: Option<&Path>,
        flags: VfsOpenFlags,
    ) -> Result<(Self::File, VfsOpenFlags)> {
        checkpoint_or_abort(cx)?;

        let is_temp = path.is_none();
        let mut resolved = if let Some(path) = path {
            resolve_path(path)?
        } else {
            self.next_temp_path()?
        };

        let is_create = path.is_none() || flags.contains(VfsOpenFlags::CREATE);
        let is_rw = path.is_none() || flags.contains(VfsOpenFlags::READWRITE) || is_create;
        let is_exclusive_create = is_create && flags.contains(VfsOpenFlags::EXCLUSIVE);

        if !is_create && !resolved.exists() {
            return Err(FrankenError::CannotOpen { path: resolved });
        }

        let mut created_db_file = false;
        let file = loop {
            let mut options = windows_open_options();
            options.read(true);
            if is_rw {
                options.write(true);
            }
            if is_create {
                options.create_new(true);
            }

            match options.open(&resolved) {
                Ok(file) => {
                    created_db_file = is_create;
                    break file;
                }
                Err(err) if is_temp && err.kind() == std::io::ErrorKind::AlreadyExists => {
                    resolved = self.next_temp_path()?;
                }
                Err(err)
                    if is_create
                        && !is_temp
                        && !is_exclusive_create
                        && err.kind() == std::io::ErrorKind::AlreadyExists =>
                {
                    let mut open_options = windows_open_options();
                    open_options.read(true);
                    if is_rw {
                        open_options.write(true);
                    }
                    match open_options.open(&resolved) {
                        Ok(file) => break file,
                        Err(err) if err.kind() == std::io::ErrorKind::NotFound => {}
                        Err(err) => return Err(FrankenError::Io(err)),
                    }
                }
                Err(err) => {
                    return Err(if err.kind() == std::io::ErrorKind::NotFound {
                        FrankenError::CannotOpen { path: resolved }
                    } else {
                        FrankenError::Io(err)
                    });
                }
            }
        };

        let owner_id = next_owner_id();
        let shm_path = sqlite_shm_path(&resolved);

        let delete_on_close = flags.contains(VfsOpenFlags::DELETEONCLOSE) || is_temp;
        let out_flags = if is_create {
            flags | VfsOpenFlags::READWRITE
        } else {
            flags
        };
        let os_locks = match WindowsOsLockFiles::open(&resolved) {
            Ok(os_locks) => os_locks,
            Err(err) => {
                drop(file);
                if created_db_file {
                    let _ = fs::remove_file(&resolved);
                }
                return Err(err);
            }
        };

        Ok((
            WindowsFile {
                path: resolved,
                file: Some(file),
                os_locks: Some(os_locks),
                owner_id,
                lock_level: LockLevel::None,
                delete_on_close,
                shm_path,
                shm_state: None,
            },
            out_flags,
        ))
    }

    fn delete(&self, _cx: &Cx, path: &Path, _sync_dir: bool) -> Result<()> {
        let resolved = resolve_path(path)?;
        if resolved.exists() {
            fs::remove_file(&resolved)?;
        }
        let shm_path = sqlite_shm_path(&resolved);
        if shm_path.exists() {
            fs::remove_file(shm_path)?;
        }
        try_remove_windows_lock_sidecars(&resolved);
        Ok(())
    }

    fn access(&self, _cx: &Cx, path: &Path, flags: AccessFlags) -> Result<bool> {
        let resolved = resolve_path(path)?;
        if !resolved.exists() {
            return Ok(false);
        }
        match flags {
            f if f == AccessFlags::EXISTS => Ok(true),
            f if f == AccessFlags::READ => {
                let mut options = windows_open_options();
                Ok(options.read(true).open(resolved).is_ok())
            }
            _ => {
                let mut options = windows_open_options();
                Ok(options.read(true).write(true).open(resolved).is_ok())
            }
        }
    }

    fn full_pathname(&self, _cx: &Cx, path: &Path) -> Result<PathBuf> {
        resolve_path(path)
    }
}

/// A file handle opened by [`WindowsVfs`].
#[derive(Debug)]
pub struct WindowsFile {
    path: PathBuf,
    file: Option<File>,
    os_locks: Option<WindowsOsLockFiles>,
    owner_id: u64,
    lock_level: LockLevel,
    delete_on_close: bool,
    shm_path: PathBuf,
    shm_state: Option<Arc<Mutex<WindowsShmState>>>,
}

impl WindowsFile {
    fn is_closed(&self) -> bool {
        self.file.is_none() && self.os_locks.is_none()
    }

    fn ensure_open(&self) -> Result<()> {
        if self.is_closed() {
            Err(FrankenError::internal("windows file is closed"))
        } else {
            Ok(())
        }
    }

    fn file_ref(&self) -> Result<&File> {
        self.file
            .as_ref()
            .ok_or_else(|| FrankenError::internal("windows file is closed"))
    }

    fn file_mut(&mut self) -> Result<&mut File> {
        self.file
            .as_mut()
            .ok_or_else(|| FrankenError::internal("windows file is closed"))
    }

    fn os_locks_ref(&self) -> Result<&WindowsOsLockFiles> {
        self.os_locks
            .as_ref()
            .ok_or_else(|| FrankenError::internal("windows lock files are closed"))
    }

    fn os_locks_mut(&mut self) -> Result<&mut WindowsOsLockFiles> {
        self.os_locks
            .as_mut()
            .ok_or_else(|| FrankenError::internal("windows lock files are closed"))
    }

    fn ensure_shm_state(&mut self) -> Result<Arc<Mutex<WindowsShmState>>> {
        if let Some(state) = &self.shm_state {
            return Ok(Arc::clone(state));
        }
        let state = windows_shm_table().get_or_create(&self.shm_path)?;
        {
            let mut guard = state
                .lock()
                .map_err(|_| lock_poisoned("windows shm state"))?;
            *guard.owner_refs.entry(self.owner_id).or_insert(0) += 1;
        }
        self.shm_state = Some(Arc::clone(&state));
        Ok(state)
    }

    fn release_shm_owner_state(&mut self, delete: bool) -> Result<()> {
        let Some(state_arc) = self.shm_state.take() else {
            if delete {
                drop(fs::remove_file(&self.shm_path));
            }
            return Ok(());
        };

        let orphaned = {
            let mut state = state_arc
                .lock()
                .map_err(|_| lock_poisoned("windows shm state"))?;

            for slot in &mut state.slots {
                slot.shared_holders.remove(&self.owner_id);
                if slot.exclusive_owner == Some(self.owner_id) {
                    slot.exclusive_owner = None;
                }
            }

            if let Some(count) = state.owner_refs.get_mut(&self.owner_id) {
                if *count > 1 {
                    *count -= 1;
                } else {
                    state.owner_refs.remove(&self.owner_id);
                }
            }
            state.owner_refs.is_empty()
        };

        if orphaned {
            windows_shm_table().remove_if_orphaned(&self.shm_path)?;
        }

        if delete {
            drop(fs::remove_file(&self.shm_path));
        }

        Ok(())
    }

    fn validate_shm_request(offset: u32, n: u32) -> Result<u32> {
        if n == 0 {
            return Err(FrankenError::LockFailed {
                detail: "shm_lock called with n=0".to_string(),
            });
        }
        let end = offset
            .checked_add(n)
            .ok_or_else(|| FrankenError::LockFailed {
                detail: "shm_lock range overflow".to_string(),
            })?;
        if end > WAL_TOTAL_LOCKS {
            return Err(FrankenError::LockFailed {
                detail: format!("shm_lock range {offset}..{end} exceeds WAL lock table"),
            });
        }
        Ok(end)
    }

    fn acquire_shared_slot(state: &mut WindowsShmState, slot: u32, owner_id: u64) -> Result<()> {
        let idx = to_slot_index(slot)?;
        let slot_state = state
            .slots
            .get_mut(idx)
            .ok_or_else(|| FrankenError::internal("shm slot index out of bounds"))?;
        if let Some(exclusive_owner) = slot_state.exclusive_owner {
            if exclusive_owner != owner_id {
                return Err(FrankenError::Busy);
            }
        }
        *slot_state.shared_holders.entry(owner_id).or_insert(0) += 1;
        Ok(())
    }

    fn acquire_exclusive_slot(state: &mut WindowsShmState, slot: u32, owner_id: u64) -> Result<()> {
        let idx = to_slot_index(slot)?;
        let slot_state = state
            .slots
            .get_mut(idx)
            .ok_or_else(|| FrankenError::internal("shm slot index out of bounds"))?;

        if slot_state.exclusive_owner == Some(owner_id) {
            return Ok(());
        }

        if slot_state.exclusive_owner.is_some() {
            return Err(FrankenError::Busy);
        }

        if slot_state
            .shared_holders
            .iter()
            .any(|(owner, count)| *owner != owner_id && *count > 0)
        {
            return Err(FrankenError::Busy);
        }

        slot_state.exclusive_owner = Some(owner_id);
        Ok(())
    }

    fn release_shared_slot(state: &mut WindowsShmState, slot: u32, owner_id: u64) -> Result<()> {
        let idx = to_slot_index(slot)?;
        let slot_state = state
            .slots
            .get_mut(idx)
            .ok_or_else(|| FrankenError::internal("shm slot index out of bounds"))?;
        let Some(holder_count) = slot_state.shared_holders.get_mut(&owner_id) else {
            return Err(FrankenError::LockFailed {
                detail: format!("owner {owner_id} does not hold shared SHM slot {slot}"),
            });
        };
        if *holder_count > 1 {
            *holder_count -= 1;
        } else {
            slot_state.shared_holders.remove(&owner_id);
        }
        Ok(())
    }

    fn release_exclusive_slot(state: &mut WindowsShmState, slot: u32, owner_id: u64) -> Result<()> {
        let idx = to_slot_index(slot)?;
        let slot_state = state
            .slots
            .get_mut(idx)
            .ok_or_else(|| FrankenError::internal("shm slot index out of bounds"))?;
        if slot_state.exclusive_owner != Some(owner_id) {
            return Err(FrankenError::LockFailed {
                detail: format!("owner {owner_id} does not hold exclusive SHM slot {slot}"),
            });
        }
        slot_state.exclusive_owner = None;
        Ok(())
    }
}

impl VfsFile for WindowsFile {
    fn close(&mut self, cx: &Cx) -> Result<()> {
        if self.is_closed() && self.shm_state.is_none() {
            return Ok(());
        }

        let mut first_error = None;

        if !self.is_closed() {
            if let Err(err) = self.unlock(cx, LockLevel::None) {
                first_error = Some(err);
            }
        }

        let release_result = if self.shm_state.is_some() || self.delete_on_close {
            self.release_shm_owner_state(self.delete_on_close)
        } else {
            Ok(())
        };
        if first_error.is_none() {
            first_error = release_result.err();
        }

        drop(self.os_locks.take());
        drop(self.file.take());
        self.lock_level = LockLevel::None;

        if self.delete_on_close {
            drop(fs::remove_file(&self.path));
            try_remove_windows_lock_sidecars(&self.path);
        }

        first_error.map_or(Ok(()), Err)
    }

    fn read(&self, cx: &Cx, buf: &mut [u8], offset: u64) -> Result<usize> {
        checkpoint_or_abort(cx)?;
        let mut total = 0_usize;
        while total < buf.len() {
            let read_offset = offset
                .checked_add(u64::try_from(total).map_err(|_| FrankenError::OutOfRange {
                    what: "read offset".to_string(),
                    value: total.to_string(),
                })?)
                .ok_or_else(|| FrankenError::OutOfRange {
                    what: "read offset".to_string(),
                    value: "overflow".to_string(),
                })?;
            let n = self.file_ref()?.seek_read(&mut buf[total..], read_offset)?;
            if n == 0 {
                break;
            }
            total += n;
        }
        if total < buf.len() {
            buf[total..].fill(0);
        }
        Ok(total)
    }

    fn write(&mut self, cx: &Cx, buf: &[u8], offset: u64) -> Result<()> {
        checkpoint_or_abort(cx)?;
        let mut total = 0_usize;
        while total < buf.len() {
            let write_offset = offset
                .checked_add(u64::try_from(total).map_err(|_| FrankenError::OutOfRange {
                    what: "write offset".to_string(),
                    value: total.to_string(),
                })?)
                .ok_or_else(|| FrankenError::OutOfRange {
                    what: "write offset".to_string(),
                    value: "overflow".to_string(),
                })?;
            let n = self.file_mut()?.seek_write(&buf[total..], write_offset)?;
            if n == 0 {
                return Err(FrankenError::Io(std::io::Error::new(
                    std::io::ErrorKind::WriteZero,
                    "seek_write returned 0",
                )));
            }
            total += n;
        }
        Ok(())
    }

    fn truncate(&mut self, _cx: &Cx, size: u64) -> Result<()> {
        self.file_mut()?.set_len(size)?;
        Ok(())
    }

    fn sync(&mut self, _cx: &Cx, flags: SyncFlags) -> Result<()> {
        if flags.contains(SyncFlags::DATAONLY) {
            self.file_mut()?.sync_data()?;
        } else {
            self.file_mut()?.sync_all()?;
        }
        Ok(())
    }

    fn file_size(&self, _cx: &Cx) -> Result<u64> {
        Ok(self.file_ref()?.metadata()?.len())
    }

    fn lock(&mut self, _cx: &Cx, level: LockLevel) -> Result<()> {
        if level <= self.lock_level {
            return Ok(());
        }

        let prior_level = self.lock_level;
        while self.lock_level < level {
            let next = next_lock_level(self.lock_level)
                .ok_or_else(|| FrankenError::internal("invalid lock escalation"))?;
            let lock_result = self.os_locks_mut()?.try_lock_level(next);
            if let Err(err) = lock_result {
                let highest_held_level = {
                    let os_locks = self.os_locks_mut()?;
                    let _ = os_locks.unlock_to(prior_level);
                    os_locks.highest_held_level()
                };
                self.lock_level = highest_held_level;
                return Err(err);
            }
            self.lock_level = next;
        }
        Ok(())
    }

    fn unlock(&mut self, _cx: &Cx, level: LockLevel) -> Result<()> {
        if level >= self.lock_level {
            return Ok(());
        }
        let unlock_result = self.os_locks_mut()?.unlock_to(level);
        if let Err(err) = unlock_result {
            self.lock_level = self.os_locks_mut()?.highest_held_level();
            return Err(err);
        }
        self.lock_level = level;
        Ok(())
    }

    fn check_reserved_lock(&self, _cx: &Cx) -> Result<bool> {
        self.os_locks_ref()?.reserved_locked_by_other()
    }

    fn sector_size(&self) -> u32 {
        4096
    }

    fn device_characteristics(&self) -> u32 {
        SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
    }

    #[allow(clippy::significant_drop_tightening)]
    fn shm_map(&mut self, _cx: &Cx, region: u32, size: u32, extend: bool) -> Result<ShmRegion> {
        self.ensure_open()?;
        if size == 0 {
            return Err(FrankenError::LockFailed {
                detail: "shm_map size must be > 0".to_string(),
            });
        }

        let size_usize = usize::try_from(size).map_err(|_| FrankenError::OutOfRange {
            what: "shm region size".to_string(),
            value: size.to_string(),
        })?;

        let min_len = u64::from(region)
            .checked_add(1)
            .and_then(|value| value.checked_mul(u64::from(size)))
            .ok_or_else(|| FrankenError::OutOfRange {
                what: "shm file length".to_string(),
                value: format!("region={region}, size={size}"),
            })?;

        if !extend {
            let mut needs_owner_ref = false;
            let shm_state = if let Some(state) = &self.shm_state {
                Arc::clone(state)
            } else {
                needs_owner_ref = true;
                windows_shm_table().get(&self.shm_path)?.ok_or_else(|| {
                    FrankenError::CannotOpen {
                        path: self.shm_path.clone(),
                    }
                })?
            };

            let mapped_region = {
                let mut state = shm_state
                    .lock()
                    .map_err(|_| lock_poisoned("windows shm state"))?;
                let existing = state.regions.get(&region).cloned().ok_or_else(|| {
                    FrankenError::CannotOpen {
                        path: self.shm_path.clone(),
                    }
                })?;
                if existing.len() < size_usize {
                    return Err(FrankenError::LockFailed {
                        detail: format!(
                            "shm region {region} is {} bytes, requested {size_usize} bytes without extend",
                            existing.len()
                        ),
                    });
                }
                if needs_owner_ref {
                    *state.owner_refs.entry(self.owner_id).or_insert(0) += 1;
                }
                existing
            };

            if needs_owner_ref {
                self.shm_state = Some(Arc::clone(&shm_state));
            }

            debug!(
                target: "fsqlite_vfs::windows",
                region,
                size,
                path = %self.shm_path.display(),
                "mapped windows shm region"
            );

            return Ok(mapped_region);
        }

        ensure_shm_file_len(&self.shm_path, min_len)?;
        let shm_state = self.ensure_shm_state()?;
        let mapped_region = {
            let mut state = shm_state
                .lock()
                .map_err(|_| lock_poisoned("windows shm state"))?;

            let entry = state.regions.entry(region);
            let region_ref = match entry {
                std::collections::hash_map::Entry::Occupied(occupied) => {
                    let region_ref = occupied.into_mut();
                    if region_ref.len() < size_usize {
                        region_ref.try_resize_heap(size_usize)?;
                    }
                    region_ref
                }
                std::collections::hash_map::Entry::Vacant(vacant) => {
                    vacant.insert(ShmRegion::new(size_usize))
                }
            };
            region_ref.clone()
        };

        debug!(
            target: "fsqlite_vfs::windows",
            region,
            size,
            path = %self.shm_path.display(),
            "mapped windows shm region"
        );

        Ok(mapped_region)
    }

    fn shm_lock(&mut self, _cx: &Cx, offset: u32, n: u32, flags: u32) -> Result<()> {
        self.ensure_open()?;
        let end = Self::validate_shm_request(offset, n)?;
        let lock_requested = flags & SQLITE_SHM_LOCK != 0;
        let unlock_requested = flags & SQLITE_SHM_UNLOCK != 0;
        if lock_requested == unlock_requested {
            return Err(FrankenError::LockFailed {
                detail: "invalid shm_lock flags (must set exactly one of LOCK/UNLOCK)".to_string(),
            });
        }

        let shared_requested = flags & SQLITE_SHM_SHARED != 0;
        let exclusive_requested = flags & SQLITE_SHM_EXCLUSIVE != 0;
        if shared_requested == exclusive_requested {
            return Err(FrankenError::LockFailed {
                detail: "invalid shm_lock flags (must set exactly one of SHARED/EXCLUSIVE)"
                    .to_string(),
            });
        }

        let shm_state = self.ensure_shm_state()?;
        let mut state = shm_state
            .lock()
            .map_err(|_| lock_poisoned("windows shm state"))?;

        if lock_requested {
            let mut acquired: Vec<u32> = Vec::new();
            for slot in offset..end {
                let result = if exclusive_requested {
                    Self::acquire_exclusive_slot(&mut state, slot, self.owner_id)
                } else {
                    Self::acquire_shared_slot(&mut state, slot, self.owner_id)
                };

                if let Err(err) = result {
                    for acquired_slot in acquired.into_iter().rev() {
                        let rollback = if exclusive_requested {
                            Self::release_exclusive_slot(&mut state, acquired_slot, self.owner_id)
                        } else {
                            Self::release_shared_slot(&mut state, acquired_slot, self.owner_id)
                        };
                        if rollback.is_err() {
                            break;
                        }
                    }
                    return Err(err);
                }
                acquired.push(slot);
            }
            return Ok(());
        }

        for slot in offset..end {
            if exclusive_requested {
                Self::release_exclusive_slot(&mut state, slot, self.owner_id)?;
            } else {
                Self::release_shared_slot(&mut state, slot, self.owner_id)?;
            }
        }
        Ok(())
    }

    fn shm_barrier(&self) {
        fence(Ordering::SeqCst);
    }

    fn shm_unmap(&mut self, _cx: &Cx, delete: bool) -> Result<()> {
        self.ensure_open()?;
        self.release_shm_owner_state(delete)
    }
}

impl crate::traits::AsyncVfsDataPath for WindowsFile {}

impl Drop for WindowsFile {
    fn drop(&mut self) {
        if !self.is_closed() || self.shm_state.is_some() {
            let cx = Cx::new();
            let _ = self.close(&cx);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write as _;
    use std::process::Command;
    use tempfile::tempdir;

    struct TempPathCleanup(PathBuf);

    impl Drop for TempPathCleanup {
        fn drop(&mut self) {
            let _ = fs::remove_file(&self.0);
        }
    }

    fn open_flags_create() -> VfsOpenFlags {
        VfsOpenFlags::MAIN_DB | VfsOpenFlags::CREATE | VfsOpenFlags::READWRITE
    }

    #[test]
    fn test_windowsvfs_create_and_write() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("create_write.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");

        file.write(&cx, b"hello windows", 0).expect("write");
        let mut buf = [0_u8; 13];
        let n = file.read(&cx, &mut buf, 0).expect("read");
        assert_eq!(n, 13);
        assert_eq!(&buf, b"hello windows");
    }

    #[test]
    fn test_windowsvfs_read_exact_at() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("read_at.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");
        file.write(&cx, b"0123456789", 0).expect("write");

        let mut buf = [0_u8; 4];
        let n = file.read(&cx, &mut buf, 3).expect("read");
        assert_eq!(n, 4);
        assert_eq!(&buf, b"3456");
    }

    #[test]
    fn test_windowsvfs_write_all_at() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("write_at.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");
        file.write(&cx, b"abcdefghij", 0).expect("write base");
        file.write(&cx, b"WXYZ", 2).expect("write overlay");

        let mut buf = [0_u8; 10];
        let n = file.read(&cx, &mut buf, 0).expect("read");
        assert_eq!(n, 10);
        assert_eq!(&buf, b"abWXYZghij");
    }

    #[test]
    fn test_windowsvfs_file_size_and_truncate() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("size.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");
        file.write(&cx, &[7_u8; 4096], 0).expect("write");
        assert_eq!(file.file_size(&cx).expect("size"), 4096);

        file.truncate(&cx, 1024).expect("truncate");
        assert_eq!(file.file_size(&cx).expect("size"), 1024);
    }

    #[test]
    fn test_windowsvfs_file_size() {
        test_windowsvfs_file_size_and_truncate();
    }

    #[test]
    fn test_windowsvfs_truncate() {
        test_windowsvfs_file_size_and_truncate();
    }

    #[test]
    fn test_windowsvfs_shared_memory_create_and_cross_handle() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("shm.db");
        let vfs = WindowsVfs::new();
        let (mut file_a, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open A");
        let (mut file_b, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open B");

        let region_a = file_a.shm_map(&cx, 0, 32 * 1024, true).expect("map A");
        {
            let mut guard = region_a.lock();
            guard[0] = 0xAA;
            guard[1] = 0x55;
        }

        let region_b = file_b.shm_map(&cx, 0, 32 * 1024, false).expect("map B");
        let guard = region_b.lock();
        assert_eq!(guard[0], 0xAA);
        assert_eq!(guard[1], 0x55);
        drop(guard);
    }

    #[test]
    fn test_windowsvfs_shared_memory_create() {
        test_windowsvfs_shared_memory_create_and_cross_handle();
    }

    #[test]
    fn test_windowsvfs_shared_memory_cross_handle() {
        test_windowsvfs_shared_memory_create_and_cross_handle();
    }

    #[test]
    fn test_windowsvfs_shm_resize_preserves_existing_mappings() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("shm_resize.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");

        let region_small = file.shm_map(&cx, 0, 32, true).expect("initial map");
        region_small.write_u32_le(0, 0x1122_3344).unwrap();

        let region_large = file.shm_map(&cx, 0, 64, true).expect("resized map");
        region_large.write_u32_le(0, 0x5566_7788).unwrap();
        region_large.write_u32_le(32, 0xAABB_CCDD).unwrap();

        assert_eq!(
            region_small.read_u32_le(0).unwrap(),
            0x5566_7788,
            "resizing must preserve shared backing for existing mappings"
        );
        assert_eq!(region_large.read_u32_le(32).unwrap(), 0xAABB_CCDD);
    }

    #[test]
    fn test_windowsvfs_shm_map_extend_false_rejects_missing_without_side_effects() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("shm_missing_no_extend.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");
        let shm_path = file.shm_path.clone();

        let err = file.shm_map(&cx, 2, 64, false).unwrap_err();
        assert!(
            matches!(err, FrankenError::CannotOpen { .. }),
            "missing non-extend shm_map should report CannotOpen, got {err:?}"
        );
        assert!(
            file.shm_state.is_none(),
            "failed non-extend shm_map must not register shm owner state"
        );
        assert!(
            windows_shm_table().get(&shm_path).unwrap().is_none(),
            "failed non-extend shm_map must not create a shared state entry"
        );
        assert!(
            !shm_path.exists(),
            "failed non-extend shm_map must not create a -shm file"
        );
    }

    #[test]
    fn test_windowsvfs_reserved_lock_conflicts_across_handles() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("reserved_lock.db");
        let vfs = WindowsVfs::new();
        let (mut file_a, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open A");
        let (mut file_b, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open B");

        file_a.lock(&cx, LockLevel::Shared).expect("A shared");
        file_a.lock(&cx, LockLevel::Reserved).expect("A reserved");
        assert!(
            !file_a.check_reserved_lock(&cx).unwrap(),
            "a handle should not report its own RESERVED lock as external"
        );
        assert!(
            file_b.check_reserved_lock(&cx).unwrap(),
            "other handles must observe a RESERVED-or-higher sidecar lock"
        );
        assert!(
            matches!(
                file_b.lock(&cx, LockLevel::Reserved),
                Err(FrankenError::Busy)
            ),
            "second RESERVED locker must be rejected"
        );

        file_a.unlock(&cx, LockLevel::None).expect("release A");
        file_b.lock(&cx, LockLevel::Reserved).expect("B reserved");
    }

    #[test]
    fn test_windowsvfs_exclusive_lock_conflicts_with_other_shared_handle() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("exclusive_vs_shared.db");
        let vfs = WindowsVfs::new();
        let (mut file_a, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open A");
        let (mut file_b, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open B");

        file_a.lock(&cx, LockLevel::Shared).expect("A shared");
        file_b.lock(&cx, LockLevel::Shared).expect("B shared");
        assert!(
            matches!(
                file_a.lock(&cx, LockLevel::Exclusive),
                Err(FrankenError::Busy)
            ),
            "EXCLUSIVE must upgrade the shared sidecar and conflict with another SHARED holder"
        );
        assert_eq!(
            file_a.lock_level,
            LockLevel::Shared,
            "failed EXCLUSIVE upgrade should roll back to the prior lock level"
        );
        file_a
            .lock(&cx, LockLevel::Reserved)
            .expect("failed exclusive upgrade must not strand RESERVED/PENDING sidecars");
    }

    #[test]
    fn test_windowsvfs_shm_exclusive_unlock_preserves_prior_shared_lock() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("shm_lock_downgrade.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");

        file.shm_lock(&cx, 0, 1, SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
            .expect("acquire shared");
        file.shm_lock(&cx, 0, 1, SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
            .expect("upgrade to exclusive");
        file.shm_lock(&cx, 0, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE)
            .expect("downgrade from exclusive");
        file.shm_lock(&cx, 0, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
            .expect("release preserved shared lock");
    }

    #[test]
    fn test_windowsvfs_temp_file_auto_delete() {
        let cx = Cx::new();
        let vfs = WindowsVfs::new();
        let flags = VfsOpenFlags::TEMP_DB
            | VfsOpenFlags::CREATE
            | VfsOpenFlags::READWRITE
            | VfsOpenFlags::DELETEONCLOSE;
        let (mut file, _) = vfs.open(&cx, None, flags).expect("open temp");
        let temp_path = file.path.clone();
        let lock_sidecars = windows_lock_sidecar_paths(&temp_path);
        assert!(temp_path.exists());
        for sidecar in &lock_sidecars {
            assert!(
                sidecar.exists(),
                "temporary Windows VFS handle should create {}",
                sidecar.display()
            );
        }
        file.close(&cx).expect("close");
        assert!(!temp_path.exists());
        for sidecar in &lock_sidecars {
            assert!(
                !sidecar.exists(),
                "temporary close should remove advisory lock sidecar {}",
                sidecar.display()
            );
        }
    }

    #[test]
    fn test_windowsvfs_temp_file_skips_existing_candidate() {
        let cx = Cx::new();
        let seed_base = 1_000_000_000_000_u64 + u64::from(std::process::id()) * 1_024;
        let (seed, blocker, blocker_file) = (0_u64..1_024)
            .find_map(|offset| {
                let seed = seed_base + offset;
                let blocker = env::temp_dir().join(format!("fsqlite-windows-{seed}.tmp"));
                let mut blocker_options = windows_open_options();
                blocker_options
                    .write(true)
                    .create_new(true)
                    .open(&blocker)
                    .ok()
                    .map(|file| (seed, blocker, file))
            })
            .expect("available temp candidate");
        let _blocker_cleanup = TempPathCleanup(blocker.clone());
        let mut blocker_file = blocker_file;
        blocker_file
            .write_all(b"existing temp candidate")
            .expect("write existing temp candidate");
        drop(blocker_file);
        let vfs = WindowsVfs {
            inner: Arc::new(Mutex::new(WindowsVfsInner { next_temp_id: seed })),
        };
        let flags = VfsOpenFlags::TEMP_DB
            | VfsOpenFlags::CREATE
            | VfsOpenFlags::READWRITE
            | VfsOpenFlags::DELETEONCLOSE;

        let (mut file, _) = vfs.open(&cx, None, flags).expect("open temp");
        let opened_path = file.path.clone();
        assert_ne!(
            opened_path, blocker,
            "anonymous temp open must not reuse an existing candidate path"
        );
        assert!(
            blocker.exists(),
            "temp collision handling must preserve the existing candidate file"
        );

        file.close(&cx).expect("close temp");
        assert!(
            !opened_path.exists(),
            "delete-on-close should remove the actual temp file"
        );
    }

    #[test]
    fn test_windowsvfs_open_handles_block_delete_sharing() {
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("delete_sharing.db");
        let mut options = windows_open_options();
        let _file = options
            .read(true)
            .write(true)
            .create(true)
            .truncate(false)
            .open(&path)
            .expect("open file without delete sharing");

        assert!(
            fs::remove_file(&path).is_err(),
            "Windows VFS files must reject unlink while an open handle exists"
        );
    }

    #[test]
    fn test_windowsvfs_lock_open_failure_cleans_created_shared_sidecar() {
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("partial_lock_open.db");
        let shared_path = sqlite_shared_lock_path(&path);
        let reserved_path = sqlite_reserved_lock_path(&path);
        fs::create_dir(&reserved_path).expect("reserved sidecar blocker");

        assert!(WindowsOsLockFiles::open(&path).is_err());
        assert!(
            !shared_path.exists(),
            "failed lock setup should remove the shared sidecar it just created"
        );
        assert!(
            reserved_path.is_dir(),
            "cleanup must not disturb the path that caused the open failure"
        );
    }

    #[test]
    fn test_windowsvfs_open_failure_cleans_created_db_file() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("partial_vfs_open.db");
        let shared_path = sqlite_shared_lock_path(&path);
        let reserved_path = sqlite_reserved_lock_path(&path);
        fs::create_dir(&reserved_path).expect("reserved sidecar blocker");
        let vfs = WindowsVfs::new();
        let flags = open_flags_create() | VfsOpenFlags::EXCLUSIVE | VfsOpenFlags::DELETEONCLOSE;

        assert!(vfs.open(&cx, Some(&path), flags).is_err());
        assert!(
            !path.exists(),
            "failed exclusive create should remove the DB file it just created"
        );
        assert!(
            !shared_path.exists(),
            "failed lock setup should remove the shared sidecar it just created"
        );
        assert!(
            reserved_path.is_dir(),
            "cleanup must not disturb the path that caused the open failure"
        );
    }

    #[test]
    fn test_windowsvfs_plain_create_failure_cleans_created_db_file() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("partial_plain_create.db");
        let shared_path = sqlite_shared_lock_path(&path);
        let reserved_path = sqlite_reserved_lock_path(&path);
        fs::create_dir(&reserved_path).expect("reserved sidecar blocker");
        let vfs = WindowsVfs::new();

        assert!(vfs.open(&cx, Some(&path), open_flags_create()).is_err());
        assert!(
            !path.exists(),
            "failed plain create should remove the DB file it just created"
        );
        assert!(
            !shared_path.exists(),
            "failed lock setup should remove the shared sidecar it just created"
        );
        assert!(
            reserved_path.is_dir(),
            "cleanup must not disturb the path that caused the open failure"
        );
    }

    #[test]
    fn test_windowsvfs_plain_create_failure_preserves_existing_db_file() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("existing_plain_create.db");
        let shared_path = sqlite_shared_lock_path(&path);
        let reserved_path = sqlite_reserved_lock_path(&path);
        fs::write(&path, b"existing db").expect("existing db");
        fs::create_dir(&reserved_path).expect("reserved sidecar blocker");
        let vfs = WindowsVfs::new();

        assert!(vfs.open(&cx, Some(&path), open_flags_create()).is_err());
        assert_eq!(
            fs::read(&path).expect("read existing db"),
            b"existing db",
            "failed plain create must preserve an existing DB file"
        );
        assert!(
            !shared_path.exists(),
            "failed lock setup should remove only the shared sidecar it just created"
        );
        assert!(
            reserved_path.is_dir(),
            "cleanup must not disturb the path that caused the open failure"
        );
    }

    #[test]
    fn test_windowsvfs_open_failure_preserves_existing_sidecar() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("partial_vfs_open_existing_sidecar.db");
        let shared_path = sqlite_shared_lock_path(&path);
        let reserved_path = sqlite_reserved_lock_path(&path);
        fs::write(&shared_path, b"existing shared sidecar").expect("existing shared sidecar");
        fs::create_dir(&reserved_path).expect("reserved sidecar blocker");
        let vfs = WindowsVfs::new();
        let flags = open_flags_create() | VfsOpenFlags::EXCLUSIVE | VfsOpenFlags::DELETEONCLOSE;

        assert!(vfs.open(&cx, Some(&path), flags).is_err());
        assert!(
            !path.exists(),
            "failed exclusive create should remove the DB file it just created"
        );
        assert!(
            shared_path.exists(),
            "failed VFS open must preserve a sidecar it did not create"
        );
        assert!(
            reserved_path.is_dir(),
            "cleanup must not disturb the path that caused the open failure"
        );
    }

    #[test]
    fn test_windowsvfs_lock_open_failure_preserves_existing_sidecars() {
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("existing_partial_lock_open.db");
        let shared_path = sqlite_shared_lock_path(&path);
        let reserved_path = sqlite_reserved_lock_path(&path);
        let pending_path = sqlite_pending_lock_path(&path);
        fs::write(&shared_path, b"existing shared sidecar").expect("existing shared sidecar");
        fs::create_dir(&pending_path).expect("pending sidecar blocker");

        assert!(WindowsOsLockFiles::open(&path).is_err());
        assert!(
            shared_path.exists(),
            "failed lock setup must not remove a sidecar it did not create"
        );
        assert!(
            !reserved_path.exists(),
            "failed lock setup should remove the reserved sidecar it just created"
        );
        assert!(
            pending_path.is_dir(),
            "cleanup must not disturb the path that caused the open failure"
        );
    }

    #[test]
    fn test_windowsvfs_delete_on_close_is_idempotent() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("idempotent_close.db");
        let vfs = WindowsVfs::new();
        let flags = open_flags_create() | VfsOpenFlags::DELETEONCLOSE;
        let (mut file, _) = vfs
            .open(&cx, Some(&path), flags)
            .expect("open delete-on-close file");
        let shm_path = file.shm_path.clone();
        let lock_sidecars = windows_lock_sidecar_paths(&path);

        file.close(&cx).expect("first close");
        assert!(!path.exists(), "first close should delete the DB file");

        fs::write(&path, b"replacement db").expect("replacement db");
        fs::write(&shm_path, b"replacement shm").expect("replacement shm");
        for sidecar in &lock_sidecars {
            fs::write(sidecar, b"replacement lock").expect("replacement sidecar");
        }

        file.close(&cx).expect("second close");
        assert!(path.exists(), "second close must be a no-op");
        assert!(
            shm_path.exists(),
            "second close must not delete replacement SHM"
        );
        for sidecar in &lock_sidecars {
            assert!(
                sidecar.exists(),
                "second close must not delete replacement sidecar {}",
                sidecar.display()
            );
        }
    }

    #[test]
    fn test_windowsvfs_shm_rejects_use_after_close() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("closed_shm.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");

        file.close(&cx).expect("close file");
        assert!(
            matches!(
                file.shm_map(&cx, 0, 32 * 1024, true),
                Err(FrankenError::Internal(_))
            ),
            "closed Windows handles must not recreate SHM state"
        );
        assert!(
            matches!(
                file.shm_lock(&cx, 0, 1, SQLITE_SHM_LOCK | SQLITE_SHM_SHARED),
                Err(FrankenError::Internal(_))
            ),
            "closed Windows handles must reject SHM locks"
        );
        assert!(
            matches!(file.shm_unmap(&cx, false), Err(FrankenError::Internal(_))),
            "closed Windows handles must reject SHM unmap"
        );
    }

    #[test]
    fn test_windowsvfs_delete_removes_lock_sidecars() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("delete_sidecars.db");
        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");
        let lock_sidecars = windows_lock_sidecar_paths(&path);

        for sidecar in &lock_sidecars {
            assert!(
                sidecar.exists(),
                "opening the Windows VFS handle should create {}",
                sidecar.display()
            );
        }

        file.close(&cx).expect("close file");

        vfs.delete(&cx, &path, false).expect("delete file");
        assert!(!path.exists(), "Vfs::delete should remove the main DB");
        for sidecar in &lock_sidecars {
            assert!(
                !sidecar.exists(),
                "Vfs::delete should remove advisory lock sidecar {}",
                sidecar.display()
            );
        }
    }

    #[test]
    fn test_windowsvfs_sector_size_detection() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("sector.db");
        let vfs = WindowsVfs::new();
        let (file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");

        let size = file.sector_size();
        assert!(size.is_power_of_two());
        assert!(size >= 512);
    }

    #[test]
    fn test_windowsvfs_device_characteristics() {
        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("iocap.db");
        let vfs = WindowsVfs::new();
        let (file, _) = vfs
            .open(&cx, Some(&path), open_flags_create())
            .expect("open file");

        assert_eq!(
            file.device_characteristics() & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN,
            SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
        );
    }

    #[test]
    fn test_e2e_windowsvfs_c_sqlite_interop() {
        let sqlite_available = Command::new("sqlite3")
            .arg("--version")
            .output()
            .is_ok_and(|output| output.status.success());
        if !sqlite_available {
            return;
        }

        let cx = Cx::new();
        let dir = tempdir().expect("temp dir");
        let path = dir.path().join("interop.db");
        let path_str = path.to_str().expect("path utf8");

        let create_status = Command::new("sqlite3")
            .arg(path_str)
            .arg("CREATE TABLE t(x INTEGER); INSERT INTO t(x) VALUES (1),(2),(3);")
            .status()
            .expect("run sqlite3 create");
        assert!(create_status.success());

        let vfs = WindowsVfs::new();
        let (mut file, _) = vfs
            .open(
                &cx,
                Some(&path),
                VfsOpenFlags::MAIN_DB | VfsOpenFlags::READWRITE,
            )
            .expect("open via windows vfs");
        let mut header = [0_u8; 16];
        let read = file.read(&cx, &mut header, 0).expect("read sqlite header");
        assert_eq!(read, 16);
        assert_eq!(&header, b"SQLite format 3\0");
        file.close(&cx).expect("close vfs file");

        let query_output = Command::new("sqlite3")
            .arg(path_str)
            .arg("SELECT count(*) FROM t;")
            .output()
            .expect("run sqlite3 query");
        assert!(query_output.status.success());
        let stdout = String::from_utf8(query_output.stdout).expect("utf8");
        assert_eq!(stdout.trim(), "3");
    }

    #[test]
    fn test_windowsvfs_cfg_gate() {
        let _ = std::any::type_name::<WindowsVfs>();
        let _ = std::any::type_name::<WindowsFile>();
    }
}
