// Tests for prompt_builder.mbt — Task 5.10 + 5.11

extern "js" fn _mkdtemp_pb() -> String =
  #| () => {
  #|   const fs = require("node:fs");
  #|   const os = require("node:os");
  #|   const path = require("node:path");
  #|   return fs.mkdtempSync(path.join(os.tmpdir(), "mnemo-pb-"));
  #| }

extern "js" fn _rmrf_pb(dir : String) -> Unit =
  #| (dir) => { require("node:fs").rmSync(dir, { recursive: true, force: true }); }

extern "js" fn _write_file_pb(path : String, content : String) -> Unit =
  #| (p, c) => { require("node:fs").writeFileSync(p, c, "utf8"); }

extern "js" fn _mkdir_p_pb(path : String) -> Unit =
  #| (p) => { require("node:fs").mkdirSync(p, { recursive: true }); }

// ---------------------------------------------------------------------------
// Task 5.10: truncation + context file loader tests
// ---------------------------------------------------------------------------

test "pb_truncate: short content unchanged" {
  let short = "hello world"
  assert_eq(pb_truncate_content(short), short)
}

test "pb_truncate: long content head+tail+marker" {
  let long = String::make(25000, 'A')
  let out = pb_truncate_content(long)
  assert_eq(out.has_prefix("AAAA"), true)
  assert_eq(out.has_suffix("AAAA"), true)
  assert_eq(out.contains("chars truncated"), true)
}

test "pb_find_context_file: absent returns empty" {
  let dir = _mkdtemp_pb()
  let result = pb_find_context_file(dir)
  assert_eq(result, "")
  _rmrf_pb(dir)
}

test "pb_find_context_file: CLAUDE.md in cwd" {
  let dir = _mkdtemp_pb()
  _write_file_pb(dir + "/CLAUDE.md", "# rules")
  let result = pb_find_context_file(dir)
  assert_eq(result.contains("rules"), true)
  _rmrf_pb(dir)
}

// ---------------------------------------------------------------------------
// Task 5.11: SOUL loader + build_system_prompt tests
// ---------------------------------------------------------------------------

test "pb_load_soul_md: absent returns empty" {
  let dir = _mkdtemp_pb()
  let result = pb_load_soul_md(dir)
  assert_eq(result, "")
  _rmrf_pb(dir)
}

test "pb_load_soul_md: present returns content" {
  let dir = _mkdtemp_pb()
  _write_file_pb(dir + "/SOUL.md", "Be thorough.")
  let result = pb_load_soul_md(dir)
  assert_eq(result.contains("Be thorough"), true)
  _rmrf_pb(dir)
}

test "build_system_prompt: empty config has identity" {
  let hh = _mkdtemp_pb()
  let cwd = _mkdtemp_pb()
  let prompt = build_system_prompt({
    hermes_home: hh,
    cwd,
    platform: "",
    model: "",
    available_tools: [],
    disabled_skills: [],
  })
  assert_eq(prompt.contains("Ermes Agent"), true)
  assert_eq(prompt.contains("persistent memory"), true)
  _rmrf_pb(hh)
  _rmrf_pb(cwd)
}

test "build_system_prompt: SOUL.md included when present" {
  let hh = _mkdtemp_pb()
  let cwd = _mkdtemp_pb()
  _write_file_pb(hh + "/SOUL.md", "Be very precise.")
  let prompt = build_system_prompt({
    hermes_home: hh,
    cwd,
    platform: "",
    model: "",
    available_tools: [],
    disabled_skills: [],
  })
  assert_eq(prompt.contains("SOUL.md"), true)
  assert_eq(prompt.contains("Be very precise"), true)
  _rmrf_pb(hh)
  _rmrf_pb(cwd)
}

test "build_system_prompt: context file included" {
  let hh = _mkdtemp_pb()
  let cwd = _mkdtemp_pb()
  _write_file_pb(cwd + "/CLAUDE.md", "# rules\nUse ESM.")
  let prompt = build_system_prompt({
    hermes_home: hh,
    cwd,
    platform: "",
    model: "",
    available_tools: [],
    disabled_skills: [],
  })
  assert_eq(prompt.contains("Project Context"), true)
  assert_eq(prompt.contains("Use ESM"), true)
  _rmrf_pb(hh)
  _rmrf_pb(cwd)
}

test "build_system_prompt: assembly order identity before context" {
  let hh = _mkdtemp_pb()
  let cwd = _mkdtemp_pb()
  _write_file_pb(cwd + "/CLAUDE.md", "# project rules")
  let prompt = build_system_prompt({
    hermes_home: hh,
    cwd,
    platform: "",
    model: "",
    available_tools: [],
    disabled_skills: [],
  })
  // Identity must appear before Project Context in the output
  let idx_id = pb_index_of(prompt, "Ermes Agent")
  let idx_ctx = pb_index_of(prompt, "Project Context")
  assert_eq(idx_id < idx_ctx, true)
  _rmrf_pb(hh)
  _rmrf_pb(cwd)
}

// ---------------------------------------------------------------------------
// Model-specific guidance tests
// ---------------------------------------------------------------------------

test "build_system_prompt: OpenAI guidance for gpt-4o" {
  let hh = _mkdtemp_pb()
  let cwd = _mkdtemp_pb()
  let prompt = build_system_prompt({
    hermes_home: hh,
    cwd,
    platform: "",
    model: "gpt-4o",
    available_tools: [],
    disabled_skills: [],
  })
  assert_eq(prompt.contains("Execution discipline"), true)
  assert_eq(prompt.contains("tool_persistence"), true)
  _rmrf_pb(hh)
  _rmrf_pb(cwd)
}

test "build_system_prompt: Google guidance for gemini model" {
  let hh = _mkdtemp_pb()
  let cwd = _mkdtemp_pb()
  let prompt = build_system_prompt({
    hermes_home: hh,
    cwd,
    platform: "",
    model: "gemini-2.0-flash",
    available_tools: [],
    disabled_skills: [],
  })
  assert_eq(prompt.contains("Google model operational directives"), true)
  assert_eq(prompt.contains("Absolute paths"), true)
  _rmrf_pb(hh)
  _rmrf_pb(cwd)
}

test "build_system_prompt: no model-specific guidance for claude" {
  let hh = _mkdtemp_pb()
  let cwd = _mkdtemp_pb()
  let prompt = build_system_prompt({
    hermes_home: hh,
    cwd,
    platform: "",
    model: "claude-3-5-sonnet",
    available_tools: [],
    disabled_skills: [],
  })
  assert_eq(prompt.contains("Execution discipline"), false)
  assert_eq(prompt.contains("Google model operational directives"), false)
  _rmrf_pb(hh)
  _rmrf_pb(cwd)
}