/// registry.mbt — 执行器注册表 + 能力路由(Marketplace/Dynamic 范式雏形)。
///
/// 管理执行器实例的注册与查找。默认注册 McpDelegateExecutor。
/// 支持自定义执行器(通过 register / add_ability 动态添加)。
/// R30 增强:为每个执行器登记「能力标签 abilities」(如 ["编排","json"]),并提供
/// 纯计算的能力路由 route_pick——给定任务所需能力 need 与各执行器当前负载 load,
/// 返回按「是否覆盖所需能力(全命中优先) → 负载最小 → 名称」排序的执行器候补。
/// 负载由调用方注入(引擎按 assignee 统计活跃任务),本层保持纯函数、不碰存储。

///|
/// 注册表结构体:名称 -> 名称(既有),加 名称 -> 能力标签集合。
pub struct ExecutorRegistry {
  executors : Map[String, String]
  abilities : Map[String, Array[String]]
}

///|
/// 全局注册表(使用 Once 懒初始化)。默认注册 McpDelegateExecutor 与 manual。
pub fn ExecutorRegistry::new() -> ExecutorRegistry {
  let m : Map[String, String] = Map([])
  let ab : Map[String, Array[String]] = Map([])
  // 默认注册 McpDelegateExecutor 与 manual(无能力标签)
  m.set("McpDelegateExecutor", "McpDelegateExecutor")
  m.set("manual", "manual")
  ab.set("McpDelegateExecutor", [])
  ab.set("manual", [])
  { executors: m, abilities: ab, }
}

///|
/// 注册执行器(保留既有能力标签,无则置空)。
pub fn ExecutorRegistry::register(
  self : ExecutorRegistry,
  name : String,
) -> ExecutorRegistry {
  let m = self.executors
  m.set(name, name)
  if self.abilities.get(name) is None {
    ignore(self.abilities.set(name, []))
  }
  { executors: m, abilities: self.abilities, }
}

///|
/// 为已注册执行器登记(或覆盖)能力标签集合。
pub fn ExecutorRegistry::add_ability(
  self : ExecutorRegistry,
  name : String,
  a : Array[String],
) -> ExecutorRegistry {
  let m = self.executors
  m.set(name, name)
  ignore(self.abilities.set(name, a))
  { executors: m, abilities: self.abilities, }
}

///|
/// 查询执行器的能力标签(未注册/无标签返回空数组)。
pub fn ExecutorRegistry::abilities_of(
  self : ExecutorRegistry,
  name : String,
) -> Array[String] {
  match self.abilities.get(name) {
    Some(a) => a
    None => []
  }
}

///|
/// 检查执行器是否已注册
pub fn ExecutorRegistry::has(self : ExecutorRegistry, name : String) -> Bool {
  self.executors.get(name) is Some(_)
}

///|
/// 列出所有已注册执行器
pub fn ExecutorRegistry::list(self : ExecutorRegistry) -> Array[String] {
  let names : Array[String] = []
  for k in self.executors.keys() {
    names.push(k)
  }
  names
}

///|
/// 获取执行器(返回名称,实际构造由调用方完成)
pub fn ExecutorRegistry::get(self : ExecutorRegistry, name : String) -> String? {
  self.executors.get(name)
}

///|
/// 便捷函数:判断是否为合法执行器名称
pub fn is_valid_executor(name : String) -> Bool {
  name == "McpDelegateExecutor" || name == "manual"
}

///|
/// 把 `need` 打散成能力标签数组:按 `,`、`,`、空格、`、` 分隔,去掉空串。
pub fn split_need_tags(need : String) -> Array[String] {
  let out : Array[String] = []
  let mut cur = ""
  for c in need {
    let ch = c.to_string()
    if ch == "," || ch == "," || ch == " " || ch == "、" {
      if cur != "" {
        out.push(cur)
        cur = ""
      }
    } else {
      cur = cur + ch
    }
  }
  if cur != "" {
    out.push(cur)
  }
  out
}

///|
/// 该执行器对 need 的能力覆盖率 0..1:命中所需标签数 / 所需标签总数。
/// need 为空(无可比性)返回 _load-only_ 语义,score 记为 0(由调用方按负载兜底)。
pub fn ability_coverage(ab : Array[String], need : Array[String]) -> Double {
  if need.is_empty() {
    return 0.0
  }
  let mut hit = 0
  for t in need {
    for a in ab {
      if a == t {
        hit = hit + 1
        break
      }
    }
  }
  // R1 bugfind:unprotected-division——`need` 可为空(调用方误传空能力集)
  let need_safe = if need.length() > 0 { need.length() } else { 1 }
  hit.to_double() / need_safe.to_double()
}

///|
/// 纯计算能力路由:按 { 覆盖率 desc, 负载 asc, 名称 asc } 排序注册的执行器,
/// 返回候选列表(每个带 name/coverage/load/abilities)。load 由调用方从 store 注入
/// (assignee 名下的活跃任务数),本层不读存储。
pub fn ExecutorRegistry::route_pick(
  self : ExecutorRegistry,
  need : String,
  load : Map[String, Int32],
) -> Json {
  let tags = split_need_tags(need)
  // 汇总每条候选:覆盖率 + 负载
  let rows : Array[Json] = []
  for name in self.list() {
    let cov = ability_coverage(self.abilities_of(name), tags)
    let ld = match load.get(name) {
      Some(n) => n
      None => 0
    }
    rows.push(
      Json::object({
        "name": Json::string(name),
        "coverage": Json::number(cov),
        "load": Json::number(ld.to_double()),
        "abilities": Json::array(
          self.abilities_of(name).map(fn(s) { Json::string(s) }),
        ),
      }),
    )
  }
  // 稳定排序:coverage desc → load asc → name asc
  rows.sort_by(fn(a : Json, b : Json) -> Int32 {
    let ac = num(a, "coverage")
    let bc = num(b, "coverage")
    if ac != bc {
      if ac > bc {
        -1
      } else {
        1
      }
    } else {
      let al = num(a, "load")
      let bl = num(b, "load")
      if al != bl {
        if al < bl {
          -1
        } else {
          1
        }
      } else {
        let an = str(a, "name")
        let bn = str(b, "name")
        if an < bn {
          -1
        } else {
          1
        }
      }
    }
  })
  let best : Json = if rows.is_empty() { Json::null() } else { rows[0] }
  Json::object({
    "need": Json::string(need),
    "parsed": Json::array(tags.map(fn(s) { Json::string(s) })),
    "count": Json::number(rows.length().to_double()),
    "candidates": Json::array(rows),
    "best": best,
  })
}

///|
/// 历史信任轴路由(R80,SwarmHarness 蒸馏):在 route_pick 排序里加 trust 轴——
/// 排序键 coverage desc → trust desc → load asc → name asc。trust 由调用方注入
/// (执行者历史验收通过率,无历史取 0.5 中性)。原 route_pick 签名保留零回归。
pub fn ExecutorRegistry::route_pick_with_trust(
  self : ExecutorRegistry,
  need : String,
  load : Map[String, Int32],
  trust : Map[String, Double],
) -> Json {
  let tags = split_need_tags(need)
  let rows : Array[Json] = []
  for name in self.list() {
    let cov = ability_coverage(self.abilities_of(name), tags)
    let ld = match load.get(name) {
      Some(n) => n
      None => 0
    }
    let tr = match trust.get(name) {
      Some(d) => d
      None => 0.5
    }
    rows.push(
      Json::object({
        "name": Json::string(name),
        "coverage": Json::number(cov),
        "trust": Json::number(tr),
        "load": Json::number(ld.to_double()),
        "abilities": Json::array(
          self.abilities_of(name).map(fn(s) { Json::string(s) }),
        ),
      }),
    )
  }
  rows.sort_by(fn(a : Json, b : Json) -> Int32 {
    let ac = num(a, "coverage")
    let bc = num(b, "coverage")
    if ac != bc {
      if ac > bc {
        -1
      } else {
        1
      }
    } else {
      let at = num(a, "trust")
      let bt = num(b, "trust")
      if at != bt {
        if at > bt {
          -1
        } else {
          1
        }
      } else {
        let al = num(a, "load")
        let bl = num(b, "load")
        if al != bl {
          if al < bl {
            -1
          } else {
            1
          }
        } else {
          let an = str(a, "name")
          let bn = str(b, "name")
          if an < bn {
            -1
          } else {
            1
          }
        }
      }
    }
  })
  let best : Json = if rows.is_empty() { Json::null() } else { rows[0] }
  Json::object({
    "need": Json::string(need),
    "parsed": Json::array(tags.map(fn(s) { Json::string(s) })),
    "count": Json::number(rows.length().to_double()),
    "candidates": Json::array(rows),
    "best": best,
    "basis": Json::string(
      "能力覆盖 → 历史信任(验收通过率) → 负载 → 名称(R80)",
    ),
  })
}

///|
/// Agora 置信度校准拍卖(R87,Agora arXiv 2607.09600 蒸馏):把执行者分派从"排序推荐"
/// 升级为"按出价竞拍"。每个已注册执行者对任务所需能力 need 出价(显式 bid,缺省按
/// 能力覆盖率自动出价),经校准系数 `1 - |出价 - 历史验收通过率|` 折扣——防"胜者诅咒":
/// 过度自信(出价高而兑现差)的执行者被惩罚;再乘负载折扣 `1/(1+负载)` 得拍卖分。
/// 能力覆盖 > 0 方可竞拍(能力不匹配不进入拍卖)。纯计算:need/load/trust/bid 均由
/// 调用方注入,本层不读存储。排序:拍卖分 desc → 名称 asc。
pub fn ExecutorRegistry::auction_pick(
  self : ExecutorRegistry,
  need : String,
  load : Map[String, Int32],
  trust : Map[String, Double],
  bid : Map[String, Double],
) -> Json {
  let tags = split_need_tags(need)
  let rows : Array[Json] = []
  for name in self.list() {
    let cov = ability_coverage(self.abilities_of(name), tags)
    if cov > 0.0 {
      let bd0 = match bid.get(name) {
        Some(d) => d
        None => cov
      }
      // 出价夹到 0..1(防止调用方传入越界置信度)
      let bd = if bd0 < 0.0 { 0.0 } else if bd0 > 1.0 { 1.0 } else { bd0 }
      let tr = match trust.get(name) {
        Some(d) => d
        None => 0.5
      }
      // 校准 = 1 - |出价 - 历史验收通过率|(Agora:按校准能力而非原始置信度拍卖)
      let diff = if bd > tr { bd - tr } else { tr - bd }
      let cal = 1.0 - diff
      let ld = match load.get(name) {
        Some(n) => n
        None => 0
      }
      // 负载折扣:活跃任务越多拍卖分越低(负载均衡)
      let lf = 1.0 / (ld + 1).to_double()
      let score = bd * cal * lf
      rows.push(
        Json::object({
          "name": Json::string(name),
          "coverage": Json::number(cov),
          "bid": Json::number(bd),
          "trust": Json::number(tr),
          "calibration": Json::number(cal),
          "load": Json::number(ld.to_double()),
          "overconfident": Json::boolean(bd > tr),
          "score": Json::number(score),
        }),
      )
    }
  }
  rows.sort_by(fn(a : Json, b : Json) -> Int32 {
    let as_ = num(a, "score")
    let bs = num(b, "score")
    if as_ != bs {
      if as_ > bs {
        -1
      } else {
        1
      }
    } else {
      let an = str(a, "name")
      let bn = str(b, "name")
      if an < bn {
        -1
      } else {
        1
      }
    }
  })
  let winner : Json = if rows.is_empty() { Json::null() } else { rows[0] }
  let note = if rows.is_empty() {
    "无能力覆盖>0 的执行者可竞拍(need 无匹配或注册表为空)"
  } else {
    let wname = str(winner, "name")
    let wbid = num(winner, "bid")
    let wtr = num(winner, "trust")
    if wbid > wtr {
      "胜者 " +
      wname +
      " 出价高于其历史兑现率,已按校准折扣计入(仍胜出说明其余竞拍者更弱)"
    } else {
      "胜者 " +
      wname +
      " 出价与历史兑现率一致(校准=1),无胜者诅咒风险"
    }
  }
  Json::object({
    "need": Json::string(need),
    "parsed": Json::array(tags.map(fn(s) { Json::string(s) })),
    "count": Json::number(rows.length().to_double()),
    "bids": Json::array(rows),
    "winner": winner,
    "basis": Json::string(
      "置信度校准拍卖(Agora arXiv2607.09600 蒸馏):能力覆盖>0 方可竞拍;出价=显式 bid 或默认按覆盖率;校准=1-|出价-历史验收通过率| 防胜者诅咒;拍卖分=出价×校准×负载折扣 1/(1+负载);score desc → 名称 asc(R87)",
    ),
    "note": Json::string(note),
  })
}

///|
/// 读 Json 对象的数值字段。
fn num(j : Json, key : String) -> Double {
  match jget(j, key) {
    Some(Json::Number(n, ..)) => n
    _ => 0.0
  }
}

///|
/// 读 Json 对象的字符串字段。
fn str(j : Json, key : String) -> String {
  match jget(j, key) {
    Some(Json::String(s)) => s
    _ => ""
  }
}