// ServiceContext(MoonBit 形态)—— 移植自 rust context.rs + spi.rs 小 SPI
// 大 SPI 走泛型参数 [R, E];小 SPI 全闭包字段(方案 §3.2/§3.4.3)。
// ITransactionTemplate 口径(D-M1-1):Unit 形态——回调内写外部可变单元带回结果。
// MoonBit 0.10 无可靠 typealias,函数类型全部内联书写。

///|
/// IOrgUserProvider 闭包组(spec/05 v1.6.0)
pub(all) struct OrgUserProviderFns {
  find_dept_leaders : (String) -> Array[String] raise @error.JeeflowError
  find_dept_main_leaders : (String) -> Array[String] raise @error.JeeflowError
  find_by_role : (String) -> Array[String] raise @error.JeeflowError
}

///|
/// IUserSearchProvider 闭包组(spec/06 §4.3/§6)
pub(all) struct UserSearchProviderFns {
  page : (@model.PageQuery) -> @model.PageResult[Map[String, Json]] raise @error.JeeflowError
  find_by_id : (String) -> Map[String, Json]? raise @error.JeeflowError
}

///|
/// IJsonProvider 闭包组(spec/05)
pub(all) struct JsonProviderFns {
  to_json : (Json) -> String
  from_json : (String) -> Json raise @error.JeeflowError
  is_json : (String) -> Bool
}

///|
/// 默认 JsonProvider(core stdlib @cjson 承载)
pub fn default_json_provider() -> JsonProviderFns {
  {
    to_json: fn(v) { v.stringify() },
    from_json: fn(s) { @json.parse_json(s) },
    is_json: fn(s) { @cjson.valid(s) },
  }
}

///|
/// IActionPermissionProvider 默认实现:wf:{action /→:}(spec/06 §2.6)
pub fn default_action_permission_provider(action : String) -> Array[String] {
  ["wf:\{action.replace(old="/", new=":")}"]
}

///|
/// FlowInterceptor 闭包形态(带 order)
pub(all) struct InterceptorFn {
  order : Int
  run : (@exec.Execution) -> Unit raise @error.JeeflowError
}

///|
/// ServiceContext —— 启动期构建、运行期只读的 SPI 注册表
pub(all) struct Ctx[R, E] {
  repository : R
  ext_repository : E
  // ── 小 SPI(闭包字段)──
  mut user_provider : ((String) -> @model.UserInfo? raise @error.JeeflowError)?
  mut org_user_provider : OrgUserProviderFns?
  mut user_search_provider : UserSearchProviderFns?
  mut json_provider : JsonProviderFns?
  mut expression_evaluator : ((String, Map[String, Json]) -> Json raise @error.JeeflowError)?
  mut id_generator : (() -> Int64 raise @error.JeeflowError)?
  mut action_permission_provider : ((String) -> Array[String])?
  mut biz_data_reader : ((String, Int64) -> Map[String, Json]? raise @error.JeeflowError)?
  // ── 按名注册表 ──
  assignment_handlers : Map[String, (@exec.Execution) -> String raise @error.JeeflowError]
  decision_handlers : Map[String, (@exec.Execution) -> String raise @error.JeeflowError]
  // ── 有序集合 ──
  interceptors : Array[InterceptorFn]
  event_listeners : Array[((@event.ProcessEvent) -> Unit raise)]
}

///|
pub fn[R, E] Ctx::new(repository : R, ext_repository : E) -> Ctx[R, E] {
  {
    repository,
    ext_repository,
    user_provider: None,
    org_user_provider: None,
    user_search_provider: None,
    json_provider: Some(default_json_provider()),
    expression_evaluator: None,
    id_generator: None,
    action_permission_provider: None,
    biz_data_reader: None,
    assignment_handlers: Map::new(),
    decision_handlers: Map::new(),
    interceptors: [],
    event_listeners: [],
  }
}

///|
pub fn[R, E] Ctx::repository(self : Ctx[R, E]) -> R {
  self.repository
}

///|
pub fn[R, E] Ctx::ext_repository(self : Ctx[R, E]) -> E {
  self.ext_repository
}

///|
pub fn[R, E] Ctx::with_user_provider(
  self : Ctx[R, E],
  p : (String) -> @model.UserInfo? raise @error.JeeflowError
) -> Ctx[R, E] {
  self.user_provider = Some(p)
  self
}

///|
pub fn[R, E] Ctx::with_org_user_provider(self : Ctx[R, E], p : OrgUserProviderFns) -> Ctx[R, E] {
  self.org_user_provider = Some(p)
  self
}

///|
pub fn[R, E] Ctx::with_user_search_provider(self : Ctx[R, E], p : UserSearchProviderFns) -> Ctx[R, E] {
  self.user_search_provider = Some(p)
  self
}

///|
pub fn[R, E] Ctx::with_expression_evaluator(
  self : Ctx[R, E],
  f : (String, Map[String, Json]) -> Json raise @error.JeeflowError
) -> Ctx[R, E] {
  self.expression_evaluator = Some(f)
  self
}

///|
pub fn[R, E] Ctx::with_id_generator(
  self : Ctx[R, E],
  f : () -> Int64 raise @error.JeeflowError
) -> Ctx[R, E] {
  self.id_generator = Some(f)
  self
}

///|
pub fn[R, E] Ctx::with_action_permission_provider(
  self : Ctx[R, E],
  f : (String) -> Array[String]
) -> Ctx[R, E] {
  self.action_permission_provider = Some(f)
  self
}

///|
pub fn[R, E] Ctx::with_biz_data_reader(
  self : Ctx[R, E],
  f : (String, Int64) -> Map[String, Json]? raise @error.JeeflowError
) -> Ctx[R, E] {
  self.biz_data_reader = Some(f)
  self
}

///|
pub fn[R, E] Ctx::json_provider_or_default(self : Ctx[R, E]) -> JsonProviderFns {
  match self.json_provider {
    Some(p) => p
    None => default_json_provider()
  }
}

///|
/// IIdGenerator:未注入时回退默认雪花(worker 0)
pub fn[R, E] Ctx::id_generator_or_default(
  self : Ctx[R, E]
) -> () -> Int64 raise @error.JeeflowError {
  match self.id_generator {
    Some(f) => f
    None => {
      let gen = @id_gen.DefaultIdGenerator::new(0L)
      fn() { gen.next_id() }
    }
  }
}

///|
/// IActionPermissionProvider:未注入用默认 wf:{action /→:}
pub fn[R, E] Ctx::permission_codes(self : Ctx[R, E], action : String) -> Array[String] {
  match self.action_permission_provider {
    Some(f) => (f)(action)
    None => default_action_permission_provider(action)
  }
}

///|
pub fn[R, E] Ctx::register_assignment_handler(
  self : Ctx[R, E],
  name : String,
  handler : (@exec.Execution) -> String raise @error.JeeflowError
) -> Unit {
  self.assignment_handlers[name] = handler
}

///|
pub fn[R, E] Ctx::register_decision_handler(
  self : Ctx[R, E],
  name : String,
  handler : (@exec.Execution) -> String raise @error.JeeflowError
) -> Unit {
  self.decision_handlers[name] = handler
}

///|
pub fn[R, E] Ctx::register_interceptor(self : Ctx[R, E], i : InterceptorFn) -> Unit {
  self.interceptors.push(i)
  self.interceptors.sort_by(fn(a, b) { a.order.compare(b.order) })
}

///|
pub fn[R, E] Ctx::register_event_listener(self : Ctx[R, E], l : (@event.ProcessEvent) -> Unit raise) -> Unit {
  self.event_listeners.push(l)
}

///|
pub fn[R, E] Ctx::event_listeners(self : Ctx[R, E]) -> Array[((@event.ProcessEvent) -> Unit raise)] {
  self.event_listeners
}

///|
pub fn[R, E] Ctx::find_assignment_handler(
  self : Ctx[R, E],
  name : String
) -> ((@exec.Execution) -> String raise @error.JeeflowError)? {
  self.assignment_handlers.get(name)
}

///|
pub fn[R, E] Ctx::find_decision_handler(
  self : Ctx[R, E],
  name : String
) -> ((@exec.Execution) -> String raise @error.JeeflowError)? {
  self.decision_handlers.get(name)
}