///|
/// 从字符串视图解析十进制整数(只接受数字,忽略其它字符)
fn digits_to_int(sv : StringView) -> Int32 {
  let s = sv.to_owned()
  let mut n = 0
  for c in s {
    let d = c.to_int() - 48
    if d >= 0 && d <= 9 {
      n = n * 10 + d
    }
  }
  n
}

///|
/// 解析 `decimal(p,s)` 形式
fn parse_decimal_type(s : String) -> DeltaType {
  let body = s.replace(old="decimal(", new="")
  let body = body.replace(old=")", new="")
  let parts = Array::from_iter(body.split(","))
  if parts.length() == 2 {
    DecimalType(
      precision=digits_to_int(parts[0]),
      scale=digits_to_int(parts[1]),
    )
  } else {
    UnknownType(raw=s)
  }
}

///|
/// 解析 array 类型的 elementType / containsNull 为单字段子树(合成名 "element")
fn parse_array_node(j : Json) -> DeltaType raise DeltaError {
  let element_type = match json_field(j, "elementType") {
    Some(t) => parse_type_node(t)
    None => UnknownType(raw="")
  }
  let contains_null = match json_field_bool(j, "containsNull") {
    Some(b) => b
    None => true
  }
  NestedType(
    kind="array",
    fields=[{ name: "element", type_: element_type, nullable: contains_null }],
  )
}

///|
/// 解析 map 类型的 keyType / valueType / valueContainsNull 为 key/value 子树
fn parse_map_node(j : Json) -> DeltaType raise DeltaError {
  let key_type = match json_field(j, "keyType") {
    Some(t) => parse_type_node(t)
    None => UnknownType(raw="")
  }
  let value_type = match json_field(j, "valueType") {
    Some(t) => parse_type_node(t)
    None => UnknownType(raw="")
  }
  let value_contains_null = match json_field_bool(j, "valueContainsNull") {
    Some(b) => b
    None => true
  }
  NestedType(
    kind="map",
    fields=[
      { name: "key", type_: key_type, nullable: false },
      { name: "value", type_: value_type, nullable: value_contains_null },
    ],
  )
}

///|
/// 解析 struct 类型的 fields 子树
fn parse_struct_node(j : Json) -> DeltaType raise DeltaError {
  let fields = parse_schema_fields(j)
  NestedType(kind="struct", fields~)
}

///|
/// 解析 Delta schema 中的单个类型节点。
///
/// 扁平原始类型按名字映射;`struct` / `array` / `map` 保留完整子树
/// (M2 起可读取),读取或写入时由上层按能力拒绝。
fn parse_type_node(j : Json) -> DeltaType raise DeltaError {
  match json_as_string(j) {
    Some(s) =>
      if s == "integer" || s == "int" {
        Int32Type
      } else if s == "long" {
        Int64Type
      } else if s == "byte" {
        ByteType
      } else if s == "short" {
        ShortType
      } else if s == "float" {
        FloatType
      } else if s == "double" {
        DoubleType
      } else if s == "boolean" {
        BooleanType
      } else if s == "string" {
        StringType
      } else if s == "binary" {
        BinaryType
      } else if s == "date" {
        DateType
      } else if s == "timestamp" {
        TimestampType
      } else if s == "timestamp_ntz" {
        UnknownType(raw="timestamp_ntz")
      } else if s.has_prefix("decimal") {
        parse_decimal_type(s)
      } else {
        UnknownType(raw=s)
      }
    None =>
      match json_field_string(j, "type") {
        Some(kind) =>
          if kind == "struct" {
            parse_struct_node(j)
          } else if kind == "array" {
            parse_array_node(j)
          } else if kind == "map" {
            parse_map_node(j)
          } else {
            UnknownType(raw=kind)
          }
        None => UnknownType(raw="")
      }
  }
}

///|
/// 解析 `fields` 数组
pub fn parse_schema_fields(j : Json) -> Array[DeltaField] raise DeltaError {
  let arr = match json_field_array(j, "fields") {
    Some(a) => a
    None => raise DeltaError::ParseError("schema.fields is missing")
  }
  let out : Array[DeltaField] = []
  for f in arr {
    let name = match json_field_string(f, "name") {
      Some(n) => n
      None => raise DeltaError::ParseError("schema field without name")
    }
    let nullable = match json_field_bool(f, "nullable") {
      Some(b) => b
      None => false
    }
    let ty = match json_field(f, "type") {
      Some(t) => parse_type_node(t)
      None => raise DeltaError::ParseError("schema field without type")
    }
    out.push({ name, type_: ty, nullable, })
  }
  out
}

///|
/// 解析 Delta schemaString(形如 `{"type":"struct","fields":[...]}`)
pub fn parse_schema(raw : String) -> DeltaSchema raise DeltaError {
  let j = @json.parse(raw) catch {
    _ => raise DeltaError::ParseError("invalid schema JSON")
  }
  let fields = parse_schema_fields(j)
  { fields, raw_json: raw, }
}

///|
/// 判断 schema 是否能在当前读取路径上安全读取;不能则给出明确原因。
/// M2 起 struct/array/map 可读;decimal/uuid 等仍拒绝(显式例外清单)。
pub fn ensure_readable_schema(schema : DeltaSchema) -> Unit raise DeltaError {
  for f in schema.fields {
    ensure_readable_type(f.name, f.type_)
  }
}

///|
fn ensure_readable_type(name : String, ty : DeltaType) -> Unit raise DeltaError {
  match ty {
    UnknownType(raw~) =>
      raise DeltaError::Unsupported(
        "unsupported delta type '\{raw}' for column '\{name}'",
      )
    DecimalType(precision~, scale~) =>
      raise DeltaError::Unsupported(
        "decimal(\{precision},\{scale}) column '\{name}' is not supported (logical type is lost by the reader)",
      )
    NestedType(fields~, ..) =>
      for f in fields {
        ensure_readable_type("\{name}.\{f.name}", f.type_)
      }
    _ => ()
  }
}

///|
/// 判断某个类型是否能由写入路径产出
pub fn is_writable_type(ty : DeltaType) -> Bool {
  match ty {
    ByteType | ShortType | Int32Type | Int64Type | FloatType | DoubleType |
    BooleanType | StringType | BinaryType | DateType | TimestampType => true
    _ => false
  }
}