///|
priv enum XlsxCellFilter {
  PresentCells
  TextCells
  QueryCells(Array[PreparedXlsxCellPredicate], OfficeQueryWorkBudget)
}

///|
/// Cell scans are command-owned CPU work, so they yield independently of I/O.
/// The work threshold prevents a small number of large strings or predicates
/// from delaying a scheduler turn until the cell-count threshold is reached.
let xlsx_cli_scan_yield_cells : Int = 256

///|
let xlsx_cli_scan_yield_work_units : Int = 64 * 1024

///|
priv struct XlsxCellPage {
  cells : Array[XlsxCellSnapshot]
  matched_total : Int
  scanned_cells : Int
  offset : Int
}

///|
priv enum XlsxRetainedJsonKind {
  RetainedCellJson
  RetainedTextJson
}

///|
priv struct XlsxJsonRetention {
  budget : OfficeOutputBudget
  records : Array[Json]
  kind : XlsxRetainedJsonKind
}

///|
fn xlsx_text_entry_json(cell : XlsxCellSnapshot) -> Json raise CliFailure {
  guard xlsx_cell_text(cell) is Some(text) else {
    raise xlsx_cli_failure(
      "office.xlsx.read_failed", "internal XLSX text retention received a cell without displayed text",
    )
  }
  Json::object({
    "path": Json::string(cell.path),
    "stability": Json::string("snapshot-relative"),
    "text": Json::string(text),
  })
}

///|
fn XlsxJsonRetention::retain(
  self : XlsxJsonRetention,
  cell : XlsxCellSnapshot,
) -> Unit raise CliFailure {
  let record = match self.kind {
    RetainedCellJson => xlsx_cell_json(cell)
    RetainedTextJson => xlsx_text_entry_json(cell)
  }
  // Charge before insertion so the live retained result is always bounded by
  // the successful-output ceiling, including on Wasm targets.
  self.budget.reserve_array_item(record, !self.records.is_empty())
  self.records.push(record)
}

///|
fn xlsx_sheet_state_name(state : @xlsx.SheetState) -> String {
  match state {
    Visible => "visible"
    Hidden => "hidden"
    VeryHidden => "very_hidden"
  }
}

///|
let xlsx_cli_max_conditional_format_open_tag_chars : Int = 32 * 1024

///|
fn XlsxConditionalFormatBudget::new(
  maximum_ranges? : Int = office_read_max_parser_items,
  maximum_work_units? : Int = office_read_max_xml_part_bytes,
) -> XlsxConditionalFormatBudget {
  { maximum_ranges, maximum_work_units, ranges: 0, work_units: 0, }
}

///|
fn XlsxConditionalFormatBudget::reserve_work(
  self : XlsxConditionalFormatBudget,
  amount : Int,
) -> Unit raise CliFailure {
  if amount < 0 || amount > self.maximum_work_units - self.work_units {
    let actual = if amount < 0 || amount > 0x7fffffff - self.work_units {
      0x7fffffff
    } else {
      self.work_units + amount
    }
    raise xlsx_resource_failure(
      "conditional-format count work units",
      self.maximum_work_units,
      actual~,
    )
  }
  self.work_units += amount
}

///|
fn XlsxConditionalFormatBudget::reserve_ranges(
  self : XlsxConditionalFormatBudget,
  amount : Int,
) -> Unit raise CliFailure {
  if amount < 0 || amount > self.maximum_ranges - self.ranges {
    let actual = if amount < 0 || amount > 0x7fffffff - self.ranges {
      0x7fffffff
    } else {
      self.ranges + amount
    }
    raise xlsx_resource_failure(
      "conditional-format ranges",
      self.maximum_ranges,
      actual~,
    )
  }
  self.ranges += amount
}

///|
// Returns only the opening tag. Conditional-format bodies can be large, but
// range counting needs just `sqref`; bounding this tag keeps the subsequent
// synchronous XML scanner below one cooperative scheduling quantum.
fn bounded_conditional_format_open_tag(
  xml : StringView,
) -> StringView raise CliFailure {
  let mut quote : UInt16? = None
  let mut index = 0
  while index < xml.length() {
    if index >= xlsx_cli_max_conditional_format_open_tag_chars {
      raise xlsx_resource_failure(
        "conditional-format opening-tag work units",
        xlsx_cli_max_conditional_format_open_tag_chars,
        actual=index + 1,
      )
    }
    let unit = xml[index]
    match quote {
      Some(expected) => if unit == expected { quote = None }
      None =>
        if unit == ('"' : UInt16) || unit == ('\'' : UInt16) {
          quote = Some(unit)
        } else if unit == ('>' : UInt16) {
          return xml[:index + 1]
        }
    }
    index += 1
  }
  xml
}

///|
async fn xlsx_conditional_format_range_count_with_budget(
  projection : XlsxProjection,
  worksheet : @xlsx.Worksheet,
  budget : XlsxConditionalFormatBudget,
) -> Int {
  projection.checkpoint()
  let mut count = 0
  let mut work_since_yield = 0
  for xml in worksheet.conditional_formats() {
    projection.checkpoint()
    budget.reserve_work(xml.length())
    let opening_tag = bounded_conditional_format_open_tag(xml)
    let fragment_count = @xlsx.conditional_format_xml_range_count_limited(
      opening_tag,
      budget.maximum_ranges,
      opening_tag.length(),
      cancelled=projection.cancelled,
    ) catch {
      ReadCancelled =>
        raise xlsx_cli_failure("office.cancelled", "XLSX read was cancelled")
      error => raise xlsx_read_failure(error, projection.file)
    }
    budget.reserve_ranges(fragment_count)
    count += fragment_count
    work_since_yield += xml.length()
    if work_since_yield >= xlsx_cli_scan_yield_work_units {
      @async.pause()
      projection.checkpoint()
      work_since_yield = 0
    }
  }
  projection.checkpoint()
  count
}

///|
async fn xlsx_sheet_summary_json(
  projection : XlsxProjection,
  sheet : XlsxSheetTarget,
  metadata : XlsxMetadataBudget,
  stored_cells : XlsxStoredCellBudget,
  conditional_formats : XlsxConditionalFormatBudget,
) -> Json {
  projection.checkpoint()
  metadata.charge_item([sheet.name, sheet.path])
  let fields : Map[String, Json] = {
    "path": Json::string(sheet.path),
    "name": Json::string(sheet.name),
    "index": Json::number((sheet.index + 1).to_double()),
  }
  match sheet.content {
    ChartSheet(chart_sheet) => {
      fields["kind"] = Json::string("chart-sheet")
      fields["state"] = Json::string(xlsx_sheet_state_name(chart_sheet.state()))
      fields["counts"] = Json::object({ "charts": Json::number(1) })
    }
    Worksheet(worksheet) => {
      fields["kind"] = Json::string("worksheet")
      fields["state"] = Json::string(xlsx_sheet_state_name(worksheet.state()))
      match xlsx_used_rect(projection, worksheet, stored_cells) {
        Some(rect) => {
          fields["max_row"] = Json::number(rect.row_hi.to_double())
          fields["max_column"] = Json::number(rect.col_hi.to_double())
          let reference = rect.range_reference(projection.file)
          let path = canonical_xlsx_range_path(sheet.name, reference)
          metadata.charge_item([reference, path])
          fields["used_range"] = Json::object({
            "path": Json::string(path),
            "reference": Json::string(reference),
            "cell_count": Json::number(rect.cell_count().to_double()),
          })
        }
        None => {
          fields["max_row"] = Json::number(0)
          fields["max_column"] = Json::number(0)
        }
      }
      let merges = worksheet.merged_cells()
      projection.checkpoint()
      let tables = worksheet.tables()
      projection.checkpoint()
      let comments = worksheet.comments()
      projection.checkpoint()
      let hyperlink_count = worksheet.hyperlink_count()
      projection.checkpoint()
      let validations = worksheet.data_validations()
      projection.checkpoint()
      let pivots = worksheet.pivot_tables()
      projection.checkpoint()
      let slicers = worksheet.slicers()
      projection.checkpoint()
      fields["counts"] = Json::object({
        "merges": Json::number(merges.length().to_double()),
        "tables": Json::number(tables.length().to_double()),
        "charts": Json::number(worksheet.charts().length().to_double()),
        "images": Json::number(worksheet.images().length().to_double()),
        "pivot_tables": Json::number(pivots.length().to_double()),
        "comments": Json::number(comments.length().to_double()),
        "hyperlinks": Json::number(hyperlink_count.to_double()),
        "data_validations": Json::number(validations.length().to_double()),
        "conditional_format_ranges": Json::number(
          xlsx_conditional_format_range_count_with_budget(
            projection, worksheet, conditional_formats,
          ).to_double(),
        ),
        "slicers": Json::number(slicers.length().to_double()),
      })
    }
  }
  projection.checkpoint()
  Json::object(fields)
}

///|
async fn xlsx_outline_data(projection : XlsxProjection) -> Json {
  projection.checkpoint()
  let metadata = XlsxMetadataBudget::new()
  let stored_cells = XlsxStoredCellBudget::new(projection.max_scan_cells)
  let conditional_formats = XlsxConditionalFormatBudget::new()
  let sheets : Array[Json] = []
  for sheet in projection.sheets {
    projection.checkpoint()
    sheets.push(
      xlsx_sheet_summary_json(
        projection, sheet, metadata, stored_cells, conditional_formats,
      ),
    )
    @async.pause()
  }
  let defined_names : Array[Json] = []
  for defined in projection.workbook.defined_names() {
    projection.checkpoint()
    metadata.charge_item([
      defined.name,
      defined.refers_to,
      defined.scope,
      defined.comment,
    ])
    let fields : Map[String, Json] = {
      "name": Json::string(defined.name),
      "refers_to": Json::string(defined.refers_to),
    }
    if defined.scope != "" {
      fields["scope"] = Json::string(defined.scope)
    }
    if defined.comment != "" {
      fields["comment"] = Json::string(defined.comment)
    }
    defined_names.push(Json::object(fields))
  }
  let fields : Map[String, Json] = {
    "schema": Json::string(@lib.SCHEMA_XLSX_OUTLINE),
    "file": Json::string(projection.file),
    "format": Json::string("xlsx"),
    "path": Json::string("/xlsx/workbook"),
    "sheet_count": Json::number(sheets.length().to_double()),
    "sheets": Json::array(sheets),
    "defined_names": Json::array(defined_names),
    "limits": Json::object({
      "max_scan_cells": Json::number(projection.max_scan_cells.to_double()),
      "max_metadata_items": Json::number(metadata.maximum_items.to_double()),
      "max_metadata_string_chars": Json::number(
        metadata.maximum_string_chars.to_double(),
      ),
    }),
  }
  if !projection.sheets.is_empty() {
    projection.checkpoint()
    let active_index = projection.workbook.get_active_sheet_index()
    guard projection.sheets.get(active_index) is Some(sheet) else {
      raise xlsx_cli_failure(
        "office.xlsx.read_failed",
        "workbook active-sheet index is outside the tab order",
        details=Json::object({
          "active_sheet_index": Json::number(active_index.to_double()),
          "sheet_count": Json::number(projection.sheets.length().to_double()),
        }),
      )
    }
    fields["active_sheet"] = Json::object({
      "path": Json::string(sheet.path),
      "name": Json::string(sheet.name),
      "index": Json::number((sheet.index + 1).to_double()),
    })
  }
  projection.checkpoint()
  Json::object(fields)
}

///|
async fn xlsx_outline_payload(
  projection : XlsxProjection,
  max_output_chars : Int,
) -> BoundedOfficePayload {
  projection.checkpoint()
  let sheets : Array[Json] = []
  let defined_names : Array[Json] = []
  let fields : Map[String, Json] = {
    "schema": Json::string(@lib.SCHEMA_XLSX_OUTLINE),
    "file": Json::string(projection.file),
    "format": Json::string("xlsx"),
    "path": Json::string("/xlsx/workbook"),
    "sheet_count": Json::number(projection.sheets.length().to_double()),
    "sheets": Json::array(sheets),
    "defined_names": Json::array(defined_names),
    "limits": Json::object({
      "max_scan_cells": Json::number(projection.max_scan_cells.to_double()),
      "max_metadata_items": Json::number(
        xlsx_cli_max_metadata_items.to_double(),
      ),
      "max_metadata_string_chars": Json::number(
        xlsx_cli_max_metadata_string_chars.to_double(),
      ),
    }),
  }
  let payload = bounded_office_payload(
    Json::object(fields),
    [],
    max_output_chars,
    "xlsx",
  )
  retain_xlsx_outline_records(projection, sheets, defined_names, payload.budget)
  if !projection.sheets.is_empty() {
    projection.checkpoint()
    let active_index = projection.workbook.get_active_sheet_index()
    guard projection.sheets.get(active_index) is Some(sheet) else {
      raise xlsx_cli_failure(
        "office.xlsx.read_failed",
        "workbook active-sheet index is outside the tab order",
        details=Json::object({
          "active_sheet_index": Json::number(active_index.to_double()),
          "sheet_count": Json::number(projection.sheets.length().to_double()),
        }),
      )
    }
    let active = Json::object({
      "path": Json::string(sheet.path),
      "name": Json::string(sheet.name),
      "index": Json::number((sheet.index + 1).to_double()),
    })
    payload.budget.reserve_json_field("active_sheet", active, true)
    fields["active_sheet"] = active
  }
  projection.checkpoint()
  payload
}

///|
fn xlsx_raw_value_json(value : @xlsx.CellValue) -> Json {
  match value {
    String(text) =>
      Json::object({
        "type": Json::string("string"),
        "value": Json::string(text),
      })
    Numeric(number) =>
      Json::object({
        "type": Json::string("number"),
        "value": Json::number(number),
      })
    Bool(flag) =>
      Json::object({
        "type": Json::string("bool"),
        "value": Json::boolean(flag),
      })
    Error(code) =>
      Json::object({
        "type": Json::string("error"),
        "value": Json::string(code),
      })
  }
}

///|
fn xlsx_cell_json(cell : XlsxCellSnapshot) -> Json {
  let fields : Map[String, Json] = {
    "path": Json::string(cell.path),
    "reference": Json::string(cell.reference),
    "row": Json::number(cell.row.to_double()),
    "column": Json::number(cell.column.to_double()),
  }
  match cell.formatted {
    Some(value) => fields["value"] = Json::string(value)
    None => ()
  }
  match cell.raw {
    Some(value) => fields["raw"] = xlsx_raw_value_json(value)
    None => ()
  }
  match cell.formula {
    Some(value) => fields["formula"] = Json::string(value)
    None => ()
  }
  if cell.style_id != 0 {
    fields["style_id"] = Json::number(cell.style_id.to_double())
  }
  Json::object(fields)
}

///|
fn xlsx_styles_json(
  projection : XlsxProjection,
  cells : Array[XlsxCellSnapshot],
) -> Json raise CliFailure {
  let fields : Map[String, Json] = Map([])
  retain_xlsx_styles(projection, cells, fields)
  Json::object(fields)
}

///|
fn retain_xlsx_styles(
  projection : XlsxProjection,
  cells : Array[XlsxCellSnapshot],
  fields : Map[String, Json],
  retention_budget? : OfficeOutputBudget,
) -> Unit raise CliFailure {
  projection.checkpoint()
  for cell in cells {
    projection.checkpoint()
    if cell.style_id != 0 {
      let key = cell.style_id.to_string()
      if !fields.contains(key) {
        let style = xlsx_call(projection.file, () => {
          projection.workbook.get_style(cell.style_id)
        })
        let value = @inspect.style_to_json(style)
        match retention_budget {
          Some(budget) =>
            budget.reserve_json_field(key, value, !fields.is_empty())
          None => ()
        }
        fields[key] = value
      }
    }
  }
  projection.checkpoint()
}

///|
fn xlsx_cells_json(
  projection : XlsxProjection,
  cells : Array[XlsxCellSnapshot],
) -> Array[Json] raise CliFailure {
  let values : Array[Json] = []
  for cell in cells {
    projection.checkpoint()
    values.push(xlsx_cell_json(cell))
  }
  projection.checkpoint()
  values
}

///|
fn xlsx_cell_text(cell : XlsxCellSnapshot) -> String? {
  match cell.formatted {
    Some(value) if value != "" => Some(value)
    // A cached result was present and intentionally formatted to blank (for
    // example with `;;;`). Do not replace Excel's blank display with formula
    // source text. `None` can also mean lazy formatting has not run yet, so
    // raw presence remains the authoritative distinction.
    _ if cell.raw is Some(_) => None
    _ =>
      match cell.formula {
        Some(formula) if formula != "" => Some("=" + formula)
        None => None
        _ => None
      }
  }
}

///|
fn XlsxCellFilter::needs_formatted(self : XlsxCellFilter) -> Bool {
  match self {
    TextCells => true
    PresentCells | QueryCells(_, _) => false
  }
}

///|
async fn XlsxCellFilter::matches(
  self : XlsxCellFilter,
  cell : XlsxCellSnapshot,
) -> Bool {
  match self {
    PresentCells => cell.is_present()
    TextCells => xlsx_cell_text(cell) is Some(_)
    QueryCells(predicates, work) => xlsx_cell_matches(cell, predicates, work)
  }
}

///|
fn XlsxCellFilter::work_used(self : XlsxCellFilter) -> Int {
  match self {
    QueryCells(_, work) => work.used
    PresentCells | TextCells => 0
  }
}

///|
fn xlsx_query_filter(
  predicates : Array[XlsxCellPredicate],
) -> XlsxCellFilter raise CliFailure {
  let work = OfficeQueryWorkBudget::new(
    office_cli_max_query_predicate_work_units,
    format="xlsx",
  )
  QueryCells(prepare_xlsx_query_predicates(predicates, work), work)
}

///|
async fn collect_xlsx_cell_page(
  projection : XlsxProjection,
  regions : Array[XlsxScanRegion],
  filter : XlsxCellFilter,
  offset : Int,
  limit : Int,
  format_work_maximum? : Int = xlsx_cli_max_format_work_units,
  retention? : XlsxJsonRetention,
) -> XlsxCellPage {
  projection.checkpoint()
  @async.pause()
  let scan = XlsxScanBudget::new(
    projection.max_scan_cells,
    format_work_maximum~,
    cancelled=projection.cancelled,
  )
  let cells : Array[XlsxCellSnapshot] = []
  let mut matched = 0
  let mut yielded_cells = 0
  let mut yielded_work = filter.work_used()
  for region in regions {
    projection.checkpoint()
    for row in region.rect.row_lo..<=region.rect.row_hi {
      for column in region.rect.col_lo..<=region.rect.col_hi {
        let cell = xlsx_cell_snapshot(
          projection,
          region.sheet,
          row,
          column,
          scan,
        )
        if filter.needs_formatted() {
          cell.ensure_formatted(projection, scan)
        }
        if filter.matches(cell) {
          if matched >= offset && cells.length() < limit {
            cell.ensure_formatted(projection, scan)
            match retention {
              Some(value) => value.retain(cell)
              None => ()
            }
            cells.push(cell)
          }
          matched += 1
        }
        let work = scan.strings.used + scan.formatting.used + filter.work_used()
        if scan.scanned - yielded_cells >= xlsx_cli_scan_yield_cells ||
          work - yielded_work >= xlsx_cli_scan_yield_work_units {
          @async.pause()
          yielded_cells = scan.scanned
          yielded_work = work
        }
      }
    }
  }
  projection.checkpoint()
  @async.pause()
  { cells, matched_total: matched, scanned_cells: scan.scanned, offset, }
}

///|
async fn retain_xlsx_outline_records(
  projection : XlsxProjection,
  sheets : Array[Json],
  defined_names : Array[Json],
  budget : OfficeOutputBudget,
) -> Unit {
  let metadata = XlsxMetadataBudget::new()
  let stored_cells = XlsxStoredCellBudget::new(projection.max_scan_cells)
  let conditional_formats = XlsxConditionalFormatBudget::new()
  for sheet in projection.sheets {
    projection.checkpoint()
    let record = xlsx_sheet_summary_json(
      projection, sheet, metadata, stored_cells, conditional_formats,
    )
    budget.reserve_array_item(record, !sheets.is_empty())
    sheets.push(record)
    @async.pause()
    projection.checkpoint()
  }
  for defined in projection.workbook.defined_names() {
    projection.checkpoint()
    metadata.charge_item([
      defined.name,
      defined.refers_to,
      defined.scope,
      defined.comment,
    ])
    let record_fields : Map[String, Json] = {
      "name": Json::string(defined.name),
      "refers_to": Json::string(defined.refers_to),
    }
    if defined.scope != "" {
      record_fields["scope"] = Json::string(defined.scope)
    }
    if defined.comment != "" {
      record_fields["comment"] = Json::string(defined.comment)
    }
    let record = Json::object(record_fields)
    budget.reserve_array_item(record, !defined_names.is_empty())
    defined_names.push(record)
  }
  projection.checkpoint()
}

///|
fn update_bounded_xlsx_page_fields(
  fields : Map[String, Json],
  page : XlsxCellPage,
  budget : OfficeOutputBudget,
) -> Unit raise CliFailure {
  let returned = page.cells.length()
  let truncated = page.offset + returned < page.matched_total
  budget.reserve_nonnegative_integer_growth(page.matched_total)
  budget.reserve_nonnegative_integer_growth(returned)
  budget.reserve_nonnegative_integer_growth(page.scanned_cells)
  budget.reserve_boolean_growth_from_true(truncated)
  fields["matched_total"] = Json::number(page.matched_total.to_double())
  fields["returned"] = Json::number(returned.to_double())
  fields["scanned_cells"] = Json::number(page.scanned_cells.to_double())
  fields["truncated"] = Json::boolean(truncated)
}

///|
async fn xlsx_get_data(
  projection : XlsxProjection,
  resolved : XlsxResolvedSelector,
) -> Json {
  projection.checkpoint()
  match resolved {
    Workbook(path~) => {
      let outline = xlsx_outline_data(projection)
      let outline_fields = match outline {
        Object(fields) => fields
        _ =>
          raise xlsx_cli_failure(
            "office.xlsx.read_failed", "workbook outline projection did not produce an object",
          )
      }
      Json::object({
        "schema": Json::string(@lib.SCHEMA_XLSX_ELEMENT),
        "file": Json::string(projection.file),
        "format": Json::string("xlsx"),
        "path": Json::string(path),
        "kind": Json::string("workbook"),
        "stability": Json::string("stable"),
        "sheet_count": outline_fields
        .get("sheet_count")
        .unwrap_or(Json::number(0)),
        "sheets": outline_fields.get("sheets").unwrap_or(Json::array([])),
        "defined_names": outline_fields
        .get("defined_names")
        .unwrap_or(Json::array([])),
      })
    }
    Sheet(sheet) =>
      Json::object({
        "schema": Json::string(@lib.SCHEMA_XLSX_ELEMENT),
        "file": Json::string(projection.file),
        "format": Json::string("xlsx"),
        "path": Json::string(sheet.path),
        "kind": Json::string("sheet"),
        "stability": Json::string("stable"),
        "sheet": xlsx_sheet_summary_json(
          projection,
          sheet,
          XlsxMetadataBudget::new(),
          XlsxStoredCellBudget::new(projection.max_scan_cells),
          XlsxConditionalFormatBudget::new(),
        ),
      })
    Cell(sheet, rect, path~) => {
      let page = collect_xlsx_cell_page(
        projection,
        [{ sheet, rect, }],
        PresentCells,
        0,
        1,
      )
      guard page.cells.get(0) is Some(cell) else {
        raise xlsx_cli_failure(
          "office.xlsx.selector_not_found",
          "XLSX cell selector resolved to a blank, unstyled coordinate",
          details=Json::object({ "selector": Json::string(path) }),
        )
      }
      Json::object({
        "schema": Json::string(@lib.SCHEMA_XLSX_ELEMENT),
        "file": Json::string(projection.file),
        "format": Json::string("xlsx"),
        "path": Json::string(path),
        "kind": Json::string("cell"),
        "stability": Json::string("snapshot-relative"),
        "parent": Json::string(sheet.path),
        "cell": xlsx_cell_json(cell),
        "styles": xlsx_styles_json(projection, [cell]),
        "scanned_cells": Json::number(page.scanned_cells.to_double()),
      })
    }
    Range(sheet, rect, path~) => {
      let page = collect_xlsx_cell_page(
        projection,
        [{ sheet, rect, }],
        PresentCells,
        0,
        projection.max_scan_cells,
      )
      Json::object({
        "schema": Json::string(@lib.SCHEMA_XLSX_ELEMENT),
        "file": Json::string(projection.file),
        "format": Json::string("xlsx"),
        "path": Json::string(path),
        "kind": Json::string("range"),
        "stability": Json::string("snapshot-relative"),
        "parent": Json::string(sheet.path),
        "reference": Json::string(rect.range_reference(projection.file)),
        "cells": Json::array(xlsx_cells_json(projection, page.cells)),
        "styles": xlsx_styles_json(projection, page.cells),
        "scanned_cells": Json::number(page.scanned_cells.to_double()),
        "returned": Json::number(page.cells.length().to_double()),
      })
    }
  }
}

///|
async fn xlsx_get_payload(
  projection : XlsxProjection,
  resolved : XlsxResolvedSelector,
  max_output_chars : Int,
) -> BoundedOfficePayload {
  projection.checkpoint()
  match resolved {
    Workbook(path~) => {
      let sheets : Array[Json] = []
      let defined_names : Array[Json] = []
      let fields : Map[String, Json] = {
        "schema": Json::string(@lib.SCHEMA_XLSX_ELEMENT),
        "file": Json::string(projection.file),
        "format": Json::string("xlsx"),
        "path": Json::string(path),
        "kind": Json::string("workbook"),
        "stability": Json::string("stable"),
        "sheet_count": Json::number(projection.sheets.length().to_double()),
        "sheets": Json::array(sheets),
        "defined_names": Json::array(defined_names),
      }
      let bounded = bounded_office_payload(
        Json::object(fields),
        [],
        max_output_chars,
        "xlsx",
      )
      retain_xlsx_outline_records(
        projection,
        sheets,
        defined_names,
        bounded.budget,
      )
      bounded
    }
    Sheet(_) | Cell(_) => {
      let bounded = bounded_office_payload(
        xlsx_get_data(projection, resolved),
        [],
        max_output_chars,
        "xlsx",
      )
      projection.checkpoint()
      bounded
    }
    Range(sheet, rect, path~) => {
      let records : Array[Json] = []
      let styles : Map[String, Json] = Map([])
      let fields : Map[String, Json] = {
        "schema": Json::string(@lib.SCHEMA_XLSX_ELEMENT),
        "file": Json::string(projection.file),
        "format": Json::string("xlsx"),
        "path": Json::string(path),
        "kind": Json::string("range"),
        "stability": Json::string("snapshot-relative"),
        "parent": Json::string(sheet.path),
        "reference": Json::string(rect.range_reference(projection.file)),
        "cells": Json::array(records),
        "styles": Json::object(styles),
        "scanned_cells": Json::number(0),
        "returned": Json::number(0),
      }
      let bounded = bounded_office_payload(
        Json::object(fields),
        [],
        max_output_chars,
        "xlsx",
      )
      let retention : XlsxJsonRetention = {
        budget: bounded.budget,
        records,
        kind: RetainedCellJson,
      }
      let page = collect_xlsx_cell_page(
        projection,
        [{ sheet, rect, }],
        PresentCells,
        0,
        projection.max_scan_cells,
        retention~,
      )
      retain_xlsx_styles(
        projection,
        page.cells,
        styles,
        retention_budget=bounded.budget,
      )
      bounded.budget.reserve_nonnegative_integer_growth(page.scanned_cells)
      bounded.budget.reserve_nonnegative_integer_growth(page.cells.length())
      fields["scanned_cells"] = Json::number(page.scanned_cells.to_double())
      fields["returned"] = Json::number(page.cells.length().to_double())
      projection.checkpoint()
      bounded
    }
  }
}

///|
async fn xlsx_text_payload(
  projection : XlsxProjection,
  under : XlsxResolvedSelector?,
  offset : Int,
  limit : Int,
  max_output_chars : Int,
) -> BoundedOfficePayload {
  projection.checkpoint()
  let entries : Array[Json] = []
  let fields : Map[String, Json] = {
    "schema": Json::string(@lib.SCHEMA_XLSX_TEXT),
    "file": Json::string(projection.file),
    "format": Json::string("xlsx"),
    "matched_total": Json::number(0),
    "offset": Json::number(offset.to_double()),
    "limit": Json::number(limit.to_double()),
    "returned": Json::number(0),
    "truncated": Json::boolean(true),
    "scanned_cells": Json::number(0),
    "entries": Json::array(entries),
  }
  match under {
    Some(value) => fields["under"] = Json::string(value.path())
    None => ()
  }
  let bounded = bounded_office_payload(
    Json::object(fields),
    [],
    max_output_chars,
    "xlsx",
  )
  let page = collect_xlsx_cell_page(
    projection,
    xlsx_scan_regions(projection, under),
    TextCells,
    offset,
    limit,
    retention={
      budget: bounded.budget,
      records: entries,
      kind: RetainedTextJson,
    },
  )
  update_bounded_xlsx_page_fields(fields, page, bounded.budget)
  projection.checkpoint()
  bounded
}

///|
async fn xlsx_query_payload(
  projection : XlsxProjection,
  under : XlsxResolvedSelector?,
  spec : XlsxQuerySpec,
  max_output_chars : Int,
) -> BoundedOfficePayload {
  projection.checkpoint()
  let matches : Array[Json] = []
  let styles : Map[String, Json] = Map([])
  let fields : Map[String, Json] = {
    "schema": Json::string(@lib.SCHEMA_XLSX_QUERY),
    "file": Json::string(projection.file),
    "format": Json::string("xlsx"),
    "selector": Json::string(spec.selector),
    "matched_total": Json::number(0),
    "offset": Json::number(spec.offset.to_double()),
    "limit": Json::number(spec.limit.to_double()),
    "returned": Json::number(0),
    "truncated": Json::boolean(true),
    "scanned_cells": Json::number(0),
    "matches": Json::array(matches),
    "styles": Json::object(styles),
  }
  match under {
    Some(value) => fields["under"] = Json::string(value.path())
    None => ()
  }
  let bounded = bounded_office_payload(
    Json::object(fields),
    [],
    max_output_chars,
    "xlsx",
  )
  let page = collect_xlsx_cell_page(
    projection,
    xlsx_scan_regions(projection, under),
    xlsx_query_filter(spec.predicates),
    spec.offset,
    spec.limit,
    retention={
      budget: bounded.budget,
      records: matches,
      kind: RetainedCellJson,
    },
  )
  retain_xlsx_styles(
    projection,
    page.cells,
    styles,
    retention_budget=bounded.budget,
  )
  update_bounded_xlsx_page_fields(fields, page, bounded.budget)
  projection.checkpoint()
  bounded
}

///|
async fn xlsx_outline_human(
  projection : XlsxProjection,
  maximum : Int,
) -> String {
  projection.checkpoint()
  let output = DocxHumanWriter::new(maximum, format="xlsx")
  output.begin_line()
  output.write_plain("xlsx: ")
  output.write_terminal_safe(projection.file)
  output.begin_line()
  output.write_plain("workbook\t/xlsx/workbook\t")
  output.write_plain("\{projection.sheets.length()} sheets")
  let stored_cells = XlsxStoredCellBudget::new(projection.max_scan_cells)
  for sheet in projection.sheets {
    projection.checkpoint()
    output.begin_line()
    output.write_terminal_safe(sheet.path)
    output.write_char('\t')
    output.write_terminal_safe(sheet.name, single_line=true)
    match sheet.content {
      ChartSheet(_) => output.write_plain("\tchart-sheet")
      Worksheet(worksheet) => {
        output.write_plain("\tworksheet")
        match xlsx_used_rect(projection, worksheet, stored_cells) {
          Some(rect) => {
            output.write_char('\t')
            output.write_terminal_safe(rect.range_reference(projection.file))
          }
          None => output.write_plain("\tempty")
        }
      }
    }
    @async.pause()
    projection.checkpoint()
  }
  projection.checkpoint()
  output.finish()
}

///|
fn xlsx_page_human(
  projection : XlsxProjection,
  page : XlsxCellPage,
  include_kind : Bool,
  maximum : Int,
) -> String raise CliFailure {
  projection.checkpoint()
  let output = DocxHumanWriter::new(maximum, format="xlsx")
  for cell in page.cells {
    projection.checkpoint()
    output.begin_line()
    output.write_terminal_safe(cell.path)
    if include_kind {
      output.write_plain("\tcell")
    }
    match xlsx_cell_text(cell) {
      Some(text) => {
        output.write_char('\t')
        output.write_terminal_safe(text, single_line=true)
      }
      None => ()
    }
  }
  output.begin_line()
  output.write_plain(
    "# matched \{page.matched_total}; returned \{page.cells.length()}; scanned \{page.scanned_cells}; offset \{page.offset}",
  )
  projection.checkpoint()
  output.finish()
}

///|
async fn xlsx_get_human(
  projection : XlsxProjection,
  resolved : XlsxResolvedSelector,
  maximum : Int,
) -> String {
  projection.checkpoint()
  match resolved {
    Workbook(..) => xlsx_outline_human(projection, maximum)
    Sheet(sheet) => {
      projection.checkpoint()
      let output = DocxHumanWriter::new(maximum, format="xlsx")
      output.begin_line()
      output.write_terminal_safe(sheet.path)
      output.write_char('\t')
      output.write_terminal_safe(sheet.name, single_line=true)
      projection.checkpoint()
      output.finish()
    }
    Cell(sheet, rect, path~) => {
      let page = collect_xlsx_cell_page(
        projection,
        [{ sheet, rect, }],
        PresentCells,
        0,
        1,
      )
      if page.cells.is_empty() {
        raise xlsx_cli_failure(
          "office.xlsx.selector_not_found",
          "XLSX cell selector resolved to a blank, unstyled coordinate",
          details=Json::object({ "selector": Json::string(path) }),
        )
      }
      xlsx_page_human(projection, page, false, maximum)
    }
    Range(sheet, rect, ..) =>
      xlsx_page_human(
        projection,
        collect_xlsx_cell_page(
          projection,
          [{ sheet, rect, }],
          PresentCells,
          0,
          projection.max_scan_cells,
        ),
        false,
        maximum,
      )
  }
}

///|
async fn xlsx_text_human(
  projection : XlsxProjection,
  under : XlsxResolvedSelector?,
  offset : Int,
  limit : Int,
  maximum : Int,
) -> String {
  xlsx_page_human(
    projection,
    collect_xlsx_cell_page(
      projection,
      xlsx_scan_regions(projection, under),
      TextCells,
      offset,
      limit,
    ),
    false,
    maximum,
  )
}

///|
async fn xlsx_query_human(
  projection : XlsxProjection,
  under : XlsxResolvedSelector?,
  spec : XlsxQuerySpec,
  maximum : Int,
) -> String {
  xlsx_page_human(
    projection,
    collect_xlsx_cell_page(
      projection,
      xlsx_scan_regions(projection, under),
      xlsx_query_filter(spec.predicates),
      spec.offset,
      spec.limit,
    ),
    true,
    maximum,
  )
}