///|
/// 64 位主文件/WAL 静态覆盖源;只保存有界覆盖索引,按范围读取实际来源,逻辑页数以最新完整提交为准。宿主必须提供一致且不可变的配对副本。
pub struct RangeWalSource {
  priv base : &RangeSource
  priv wal : &RangeSource
  priv page_size : Int
  priv page_count : Int
  priv base_pages : Int
  priv overlay : Map[Int, Int64]
  priv inspection : RangeWalInspection
}

///|
pub extend RangeWalSource with RangeSource::{byte_length64, read_range64}

///|
/// 只读最新已提交快照;调用者负责提供同一数据库、同一时刻的不可变副本。
/// 逐帧校验配对静态范围源并构建有界最新提交覆盖索引;max_frames/max_overlay_pages 默认各 100000。宿主失败或预算不足不能回退为旧成功快照。
pub fn RangeWalSource::new(
  base : &RangeSource,
  wal : &RangeSource,
  tail_policy? : WalTailPolicy = RejectInvalidTail,
  max_frames? : Int = 100000,
  max_overlay_pages? : Int = 100000,
) -> RangeWalSource raise SqliteError {
  build_range_wal_source(
    base,
    wal,
    inspect_wal_source(wal, max_frames~),
    tail_policy,
    max_overlay_pages,
  )
}

///|
/// 使用已经完成的供帧游标创建索引;游标输入必须来自相同的不可变 WAL。
/// 从完成的 WalCursor 构造覆盖索引,不重新验证 WAL;传入源必须与供给校验时相同且不可变。未完成/取消游标拒绝构造。
pub fn RangeWalSource::from_cursor(
  base : &RangeSource,
  wal : &RangeSource,
  cursor : WalCursor,
  tail_policy? : WalTailPolicy = RejectInvalidTail,
  max_overlay_pages? : Int = 100000,
) -> RangeWalSource raise SqliteError {
  if cursor.closed {
    raise Invalid("WAL 游标已经关闭")
  }
  let report = cursor.finished.unwrap_or_else(() => {
    raise Invalid("WAL 游标尚未完成")
  })
  build_range_wal_source(
    base,
    wal,
    copy_wal_inspection(report),
    tail_policy,
    max_overlay_pages,
  )
}

///|
fn build_range_wal_source(
  base : &RangeSource,
  wal : &RangeSource,
  inspection : RangeWalInspection,
  tail_policy : WalTailPolicy,
  max_overlay_pages : Int,
) -> RangeWalSource raise SqliteError {
  if max_overlay_pages < 1 {
    raise Invalid("WAL 覆盖页预算必须为正数")
  }
  if inspection.stop_reason == WalFrameLimit {
    raise LimitExceeded(
      "WAL 帧上限不足,不能确定最新已提交快照",
    )
  }
  if tail_policy == RejectInvalidTail && inspection.stop_reason != WalEndOfFile {
    raise Invalid(
      "WAL 存在无效或截断尾部;请检查报告并显式选择 UseValidPrefix",
    )
  }
  let size = base.byte_length64()
  if size < 0L {
    raise Invalid("主文件长度不能为负数")
  }
  let base_header = if size == 0L {
    None
  } else {
    Some(parse_header(range_sqlite_read(base, 0L, 100)))
  }
  let page_size = match inspection.header {
    Some(header) => header.page_size
    None =>
      base_header.unwrap_or_else(() => {
        raise Invalid("没有 WAL 或可用主文件")
      }).page_size
  }
  if size % page_size.to_int64() != 0L {
    raise Invalid("WAL 主文件不包含完整页面")
  }
  if base_header is Some(header) && header.page_size != page_size {
    raise Invalid("WAL 与主文件 page_size 不一致")
  }
  let physical_pages = bounded_int(
    (size / page_size.to_int64()).reinterpret_as_uint64(),
    "database pages",
  )
  let mut base_pages = physical_pages
  let page_count = match inspection.database_pages {
    Some(pages) => bounded_int(pages.to_uint64(), "WAL database pages")
    None => {
      let header = base_header.unwrap_or_else(() => {
        raise Invalid("没有已提交 WAL 或可用主文件")
      })
      if header.declared_pages != 0U &&
        header.change_counter == header.version_valid_for {
        let count = bounded_int(
          header.declared_pages.to_uint64(),
          "database pages",
        )
        if count > physical_pages {
          raise Invalid("主文件声明页数超过文件长度")
        }
        count
      } else {
        physical_pages
      }
    }
  }
  if page_count < 1 {
    raise Invalid("WAL 快照页数必须为正数")
  }
  let overlay : Map[Int, Int64] = Map([])
  // 逆序保留最新版本;后续提交的缩小边界使更早的高页号版本失效。
  // 只扫描一次,避免每个提交反复遍历整张覆盖表。
  let mut retained_pages = page_count
  for i = inspection.committed_frames - 1; i >= 0; i = i - 1 {
    let frame = inspection.frames[i]
    if frame.database_pages != 0U &&
      frame.database_pages.to_uint64() < retained_pages.to_uint64() {
      retained_pages = frame.database_pages.reinterpret_as_int()
    }
    if frame.page_number.to_uint64() <= retained_pages.to_uint64() {
      let number = frame.page_number.reinterpret_as_int()
      if !overlay.contains(number) {
        if overlay.length() >= max_overlay_pages {
          raise LimitExceeded("WAL 覆盖页索引超过独立预算")
        }
        overlay[number] = frame.byte_offset + 24L
      }
    }
  }
  base_pages = Int::min(base_pages, retained_pages)
  // 文件增长的所有新页必须由 WAL 提供;避免从旧的截断残留页读取数据。
  let mut new_pages = 0
  for number, _ in overlay {
    if number > base_pages {
      new_pages = new_pages + 1
    }
  }
  if page_count > base_pages && new_pages != page_count - base_pages {
    raise Invalid("WAL 快照缺少增长后的页面")
  }
  { base, wal, page_size, page_count, base_pages, overlay, inspection, }
}

///|
/// 返回覆盖视图的 64 位 WAL 验证报告,不重新读取源;调用者不应修改报告数组。
pub fn RangeWalSource::inspection(self : RangeWalSource) -> RangeWalInspection {
  self.inspection
}

///|
/// 返回最新完整提交的逻辑页数,隔离未提交尾部和缩小后旧页。
pub fn RangeWalSource::page_count(self : RangeWalSource) -> Int {
  self.page_count
}

///|
/// 返回静态源字节长度,不执行格式检查。
pub impl RangeSource for RangeWalSource with fn byte_length64(self) {
  self.page_count.to_int64() * self.page_size.to_int64()
}

///|
/// 按源契约返回准确范围字节;范围和长度错误按实现所属的源错误类型返回。
pub impl RangeSource for RangeWalSource with fn read_range64(
  self,
  offset,
  count,
) {
  let size = self.byte_length64()
  check_source_range(size, offset, count)
  let output : FixedArray[Byte] = FixedArray::make(count, 0)
  let mut copied = 0
  while copied < count {
    let position = offset + copied.to_int64()
    let number = (position / self.page_size.to_int64()).to_int() + 1
    let in_page = (position % self.page_size.to_int64()).to_int()
    let length = Int::min(count - copied, self.page_size - in_page)
    let input = match self.overlay.get(number) {
      Some(wal_offset) =>
        range_read(self.wal, wal_offset + in_page.to_int64(), length)
      None => {
        if number > self.base_pages {
          raise HostFailure("WAL 快照页面缺失")
        }
        range_read(self.base, position, length)
      }
    }
    for i = 0; i < length; i = i + 1 {
      output[copied + i] = input[i]
    }
    copied = copied + length
  }
  Bytes::from_array(output)
}

///|
/// 从已校验的 64 位覆盖源打开 Database,使用提交逻辑页数;初始化失败没有部分检查报告,调用者仍管理源生命周期。
pub fn open_range_wal_source(
  source : RangeWalSource,
  limits? : Limits = Limits::default(),
  max_report_pages? : Int = 100000,
) -> Database raise SqliteError {
  open_data_source(
    WideSource(source),
    limits,
    Some(source.page_count),
    max_report_pages~,
  )
}

///|
/// 异步适配器使用同一个核心覆盖索引确定页来源,不重复实现提交或缩小语义。
/// 覆盖视图中页面的真实来源;MainPage/WalPage 携带页面内容起始的 Int64 字节偏移,WalPage 跳过 24 字节帧头。
pub(all) enum SnapshotPageRange {
  MainPage(Int64)
  WalPage(Int64)
} derive(Debug, Eq)

///|
pub extend SnapshotPageRange with @debug.Debug::{to_repr}

///|
pub extend SnapshotPageRange with Eq::{equal, not_equal}

///|
/// 查询逻辑页实际读取来源;返回页面内容起始的 Int64 偏移,WAL 偏移不包含 24 字节帧头。页号越界抛 Invalid。
pub fn RangeWalSource::page_range(
  self : RangeWalSource,
  number : Int,
) -> SnapshotPageRange raise SqliteError {
  if number < 1 || number > self.page_count {
    raise Invalid("页号越界:\{number}")
  }
  match self.overlay.get(number) {
    Some(offset) => WalPage(offset)
    None => MainPage((number - 1).to_int64() * self.page_size.to_int64())
  }
}