// 独立自检入口。
//
// Windows 下 `moon test` 可能受嵌套进程限制(os error 5),
// 因此提供与 `moon test` 等价的自检路径:
//   1. 一致性语料;
//   2. 扩展规则 / 检测器的公开 API 冒烟检查。

///|
fn check_extension_api() -> Array[String] {
  let failures : Array[String] = []

  // 声明式规则:命中后应当优先于内置签名
  let registry = @Mr-Houjie/mbt-filetype.Registry::new()
  registry.add_rule(
    @Mr-Houjie/mbt-filetype.Rule::new(
      "foo",
      "application/x-foo",
      "foo",
      @Mr-Houjie/mbt-filetype.Other,
      "FOO! 魔数",
      95,
      @Mr-Houjie/mbt-filetype.Matcher::magic_at(0, b"FOO!"),
    ),
  )
  let hit = @Mr-Houjie/mbt-filetype.detect_with(registry, b"FOO!rest")
  match hit.file_type {
    Some(file_type) =>
      if file_type.id != "foo" {
        failures.push("扩展规则未生效:得到 \{file_type.id}")
      }
    None => failures.push("扩展规则未生效:得到 unknown")
  }
  if hit.score != 95 {
    failures.push("扩展规则评分异常:\{hit.score}")
  }
  if registry.rule_count() != 1 {
    failures.push("Registry::rule_count 异常")
  }

  // 组合子:掩码 + 与条件
  let combo = @Mr-Houjie/mbt-filetype.Registry::new()
  combo.add_rule(
    @Mr-Houjie/mbt-filetype.Rule::new(
      "combo",
      "application/x-combo",
      "combo",
      @Mr-Houjie/mbt-filetype.Other,
      "掩码 + ASCII",
      90,
      @Mr-Houjie/mbt-filetype.Matcher::all([
        @Mr-Houjie/mbt-filetype.Matcher::magic_at(0, b"AB"),
        @Mr-Houjie/mbt-filetype.Matcher::masked_at(2, b"\x01\x00", b"\xff\x00"),
        @Mr-Houjie/mbt-filetype.Matcher::ascii_at(4, "CD"),
      ]),
    ),
  )
  let combo_hit = @Mr-Houjie/mbt-filetype.detect_with(combo, b"AB\x01\xffCD")
  match combo_hit.file_type {
    Some(file_type) =>
      if file_type.id != "combo" {
        failures.push("组合匹配器未生效:得到 \{file_type.id}")
      }
    None => failures.push("组合匹配器未生效:得到 unknown")
  }

  // 命令式检测器:内置签名未命中时兜底
  let with_detector = @Mr-Houjie/mbt-filetype.Registry::new()
  with_detector.add_detector(fn(data) {
    let is_det = data.length() >= 4 &&
      data[0].to_int() == 68 &&
      data[1].to_int() == 69 &&
      data[2].to_int() == 84 &&
      data[3].to_int() == 33
    if is_det {
      Some(
        ({
          file_type: Some({
            id: "detected",
            mime: "application/x-detected",
            ext: "det",
            category: @Mr-Houjie/mbt-filetype.Other,
          }),
          confidence: @Mr-Houjie/mbt-filetype.Certain,
          reason: "DET! 前缀",
          offset: 0,
          matched_len: 4,
          candidates: [],
          score: 100,
          evidence: [],
        } : @Mr-Houjie/mbt-filetype.Detection),
      )
    } else {
      None
    }
  })
  if with_detector.detector_count() != 1 {
    failures.push("Registry::detector_count 异常")
  }
  match @Mr-Houjie/mbt-filetype.detect_with(with_detector, b"DET!payload").file_type {
    Some(file_type) =>
      if file_type.id != "detected" {
        failures.push("自定义检测器未生效:得到 \{file_type.id}")
      }
    None => failures.push("自定义检测器未生效:得到 unknown")
  }

  failures
}

///|
fn main {
  let total = @Mr-Houjie/mbt-filetype.conformance_case_count()
  let failures = @Mr-Houjie/mbt-filetype.run_conformance()
  let api_failures = check_extension_api()
  if failures.length() == 0 && api_failures.length() == 0 {
    println("conformance: \{total} cases passed")
    println("extension api: ok")
    @sys.exit(0)
    return
  }
  for failure in failures {
    println("FAIL \{failure}")
  }
  for failure in api_failures {
    println("FAIL \{failure}")
  }
  println(
    "conformance: \{failures.length()} / \{total} failed, api: \{api_failures.length()} failed",
  )
  @sys.exit(1)
}