///|
/// 页内格式错误的分类;PageRead 表示输入或宿主读取失败。
/// 单页失败的结构化类别;PageRead 仅表示读取失败,不能直接断定格式损坏。
pub(all) enum PageDiagnosticCode {
  PageRead
  PageTypeTag
  PageHeader
  CellPointer
  CellFormat
  Freeblock
  SpaceOverlap
  UntrackedSpace
  FragmentCount
  ChildPointer
} derive(Debug, Eq)

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

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

///|
/// byte_offset 从页面起点计数;cell_index 从零计数。位置指向检查失败的字段或区间。
/// 单页错误及可定位的页内偏移/cell 下标;error 保留原始类别和具体原因。
pub(all) struct PageDiagnostic {
  code : PageDiagnosticCode
  page_number : Int
  byte_offset : Int?
  cell_index : Int?
  error : SqliteError
} derive(Debug)

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

///|
/// 空间项互不重叠,总和等于页面大小;payload 计数是 cell 声明值,不验证 overflow 链。
/// 单页空间分项,单位为字节。payload_bytes 是声明总量,local_payload_bytes 是页内部分;仅检查当前页,不验证 overflow 内容或 record 解码。
pub(all) struct PageStatistics {
  database_header_bytes : Int
  btree_header_bytes : Int
  pointer_bytes : Int
  unallocated_bytes : Int
  cell_bytes : Int
  freeblock_bytes : Int
  fragmented_bytes : Int
  reserved_bytes : Int
  payload_bytes : UInt64
  local_payload_bytes : UInt64
  max_payload_bytes : Int
  overflow_cells : Int
} derive(Debug)

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

///|
/// 仅检查指定 B-tree 页的布局;失败时不返回可能误导的部分统计。
/// 单页 B-tree 检查结果;读取失败为 Incomplete。失败时 page/statistics 可能缺失,diagnostic 保留已知位置。
pub(all) struct PageInspection {
  status : InspectionStatus
  page : Page?
  statistics : PageStatistics?
  diagnostic : PageDiagnostic?
} derive(Debug)

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

///|
priv suberror PageValidationError {
  PageInvalid(PageDiagnostic)
}

///|
fn page_invalid(
  number : Int,
  code : PageDiagnosticCode,
  byte_offset : Int,
  message : String,
  cell_index? : Int? = None,
) -> PageValidationError {
  PageInvalid({
    code,
    page_number: number,
    byte_offset: Some(byte_offset),
    cell_index,
    error: Invalid(message),
  })
}

///|
fn page_u16(
  bytes : Bytes,
  number : Int,
  byte_offset : Int,
  code : PageDiagnosticCode,
  cell_index? : Int? = None,
) -> Int raise PageValidationError {
  read_u16(bytes, byte_offset) catch {
    error =>
      raise PageInvalid({
        code,
        page_number: number,
        byte_offset: Some(byte_offset),
        cell_index,
        error,
      })
  }
}

///|
/// 仅读取指定页并校验 B-tree 布局/空间;读取失败为 Incomplete,格式错误为 Failed,保留可用诊断,不检查 record 或 overflow 链。
pub fn Database::inspect_page(self : Database, number : Int) -> PageInspection {
  let bytes = self.read_page(number) catch {
    error =>
      // 无法读取完整页时不推断文件损坏,包括宿主返回的 Invalid。
      return {
        status: Incomplete,
        page: None,
        statistics: None,
        diagnostic: Some({
          code: PageRead,
          page_number: number,
          byte_offset: None,
          cell_index: None,
          error,
        }),
      }
  }
  try self.parse_btree_page(number, bytes) catch {
    PageInvalid(diagnostic) =>
      {
        status: match diagnostic.error {
          Invalid(_) => Failed
          Unsupported(_) | LimitExceeded(_) => Incomplete
        },
        page: None,
        statistics: None,
        diagnostic: Some(diagnostic),
      }
  } noraise {
    (page, statistics) =>
      {
        status: Complete,
        page: Some(page),
        statistics: Some(statistics),
        diagnostic: None,
      }
  }
}