///|
fn field_to_string(field : StringBuilder, options : CSVOptions) -> String {
  if options.trim_spaces {
    field.to_string().trim(char_set="\n\r\t ").to_owned()
  } else {
    field.to_string()
  }
}

///|
fn[T : CSVReader] parse(
  reader : T,
  options? : CSVOptions = {
    delimiter: ',',
    allow_newlines_in_quotes: true,
    quote_char: '"',
    skip_empty_lines: true,
    trim_spaces: false,
  },
) -> Array[Array[String]] {
  let rows : Array[Array[String]] = Array::new()
  let mut row = Array::make(0, "")
  let mut field = StringBuilder::new()
  let mut in_quotes = false
  let mut record_has_content = false
  while !reader.is_eof() {
    let mut ch = reader.read_char().unwrap()

    // 处理 Windows 格式换行的 \r
    if ch == '\r' {
      if reader.peek_char() == Some('\n') {
        if in_quotes && options.allow_newlines_in_quotes {
          // 在引号内,需要同时处理 \r 和 \n
          field.write_char(ch) // 写入 \r
          reader.read_char() |> ignore // 消费 \n
          field.write_char('\n') // 写入 \n
          record_has_content = true
          continue // 继续下一轮循环
        } else {
          // 不在引号内,跳过 \r,之后将处理 \n
          continue
        }
      } else if options.allow_newlines_in_quotes && in_quotes {
        // 单独的 \r
        field.write_char(ch)
        record_has_content = true
        continue
      } else {
        // 将单独的 \r 视为换行
        ch = '\n'
      }
    }
    if in_quotes {
      if ch == options.quote_char {
        // 遇到引号,看下一个字符以判断转义或结束
        if !reader.is_eof() && reader.peek_char() == Some(options.quote_char) {
          // 连续两个引号,表示数据中的一个引号
          field.write_char(options.quote_char)
          reader.read_char() |> ignore // 跳过转义的第二个引号
          record_has_content = true
        } else {
          // 引号闭合,退出引号模式
          in_quotes = false
        }
      } else if ch == '\n' && !options.allow_newlines_in_quotes {
        // 如果不允许引号内换行但遇到了换行,强制结束引号
        in_quotes = false

        // 处理当前行
        if record_has_content || !options.skip_empty_lines {
          row.push(field_to_string(field, options))
          rows.push(row)
        }

        // 重置用于下一行
        row = Array::make(0, "")
        field = StringBuilder::new()
        record_has_content = false
      } else {
        // 引号内普通字符,加入当前字段
        field.write_char(ch)
        record_has_content = true
      }
    } else if ch == options.quote_char {
      // 遇到引号,进入引号模式(开始读取引用字段)
      // 只有当字段为空时才进入引号模式
      if field.is_empty() {
        in_quotes = true
        record_has_content = true
      } else {
        // 字段非空时遇到引号,视为普通字符
        field.write_char(ch)
        record_has_content = true
      }
    } else if ch == options.delimiter {
      // 遇到分隔符,当前字段结束
      row.push(field_to_string(field, options))
      field = StringBuilder::new() // 创建新的字段构建器
      record_has_content = true
    } else if ch == '\n' {
      // 遇到换行且不在引号内,当前记录结束
      // 检查是否为有效行(非空或配置允许空行)
      if record_has_content || !options.skip_empty_lines {
        row.push(field_to_string(field, options))
        rows.push(row)
      }

      // 重置用于下一行
      row = Array::make(0, "")
      field = StringBuilder::new()
      record_has_content = false
    } else {
      // 普通字符,累积到当前字段
      field.write_char(ch)
      record_has_content = true
    }
  }

  // 循环结束后,加入最后的字段和行(如果有)
  if record_has_content || row.length() > 0 {
    if record_has_content || !options.skip_empty_lines {
      row.push(field_to_string(field, options))
      rows.push(row)
    }
  }
  rows
}

///|
test "CSV::parse_string/carriage_return_in_quotes_not_allowed" {
  // 测试当不允许引号内换行时,引号内的\r会被视为换行并结束引号状态
  let data = "a,b,c\n1,\"line\rwith\rCRs\",3"
  let csv = CSV::parse_string(data, options={
    delimiter: ',',
    allow_newlines_in_quotes: false,
    quote_char: '"',
    skip_empty_lines: true,
    trim_spaces: true,
  })

  // 验证引号在遇到\r时被强制结束,并创建了新行
  inspect(csv.rows.length(), content="3") // 应该分成多行
  assert_eq(csv.rows[0][1], "line")
  // 后面的行会因为强制结束引号而成为新行的一部分
}

///|
test "CSV::parse_string/carriage_return_in_quotes" {
  // 测试引号内的\r在允许引号内换行的情况下被保留
  let data = "a,b,c\n1,\"line\rwith\rCRs\",3 "
  let csv = CSV::parse_string(data)
  inspect(csv.headers, content="[\"a\", \"b\", \"c\"]")

  // 验证引号内的\r被正确保留
  assert_eq(csv.rows[0][1], "line\rwith\rCRs")
  // 123
}