// router.mbt
//! 命令路由器 - 基于 Reader Monad 的现代实现

// ============ 类型定义 ============

///|
/// 路由环境(依赖注入容器)
pub struct RouteEnv[AggregateId, S, E] {
  event_store : @store.EventStore[AggregateId, E]
  snapshot_store : @store.SnapshotStore[AggregateId, S]
  event_bus : @event.EventBus[AggregateId, E]?
  logger : &Logger
  default_timeout : Int64
  default_retry : Int32
}

///|
pub fn[AggregateId, E, S] RouteEnv::new(
  event_store : @store.EventStore[AggregateId, E],
  snapshot_store : @store.SnapshotStore[AggregateId, S],
  event_bus : @event.EventBus[AggregateId, E]?,
  // logger: &Logger,
  default_timeout : Int64,
  default_retry : Int32,
) -> RouteEnv[AggregateId, S, E] {
  {
    event_store,
    snapshot_store,
    event_bus,
    logger: make_console_logger(),
    default_timeout,
    default_retry,
  }
}
// }

///|
pub(all) struct CommandConfig {
  timeout_ms : Int64
  max_retries : Int32
  consistency : Consistency
}

///|
pub fn CommandConfig::new() -> CommandConfig {
  { timeout_ms: 5000L, max_retries: 3, consistency: Consistency::Strong, }
}

///|
pub fn CommandConfig::with_timeout(
  self : CommandConfig,
  timeout_ms : Int64,
) -> CommandConfig {
  { ..self, timeout_ms, }
}

///|
pub fn CommandConfig::with_retries(
  self : CommandConfig,
  max_retries : Int32,
) -> CommandConfig {
  { ..self, max_retries, }
}

///|
pub fn CommandConfig::with_consistency(
  self : CommandConfig,
  consistency : Consistency,
) -> CommandConfig {
  { ..self, consistency, }
}

// 1. RouterBuilder

///|
pub(all) struct RouterBuilder[AggregateId, S, C, E] {
  env : RouteEnv[AggregateId, S, E]
  mut default_config : CommandConfig
  handlers : Map[String, @command.CommandHandler[S, C, E]] // 改为 Map,key 为命令类型名
}

///|
pub fn[AggregateId, S, C, E] RouterBuilder::new(
  env : RouteEnv[AggregateId, S, E],
) -> RouterBuilder[AggregateId, S, C, E] {
  { env, default_config: CommandConfig::new(), handlers: Map([]), }
}

///|
pub fn[AggregateId, S, C, E] RouterBuilder::add_handler(
  self : RouterBuilder[AggregateId, S, C, E],
  command_type : String,
  handler : @command.CommandHandler[S, C, E],
) -> RouterBuilder[AggregateId, S, C, E] {
  self.handlers[command_type] = handler
  self
}

///|
/// 批量添加处理器
pub fn[AggregateId, S, C, E] RouterBuilder::add_handlers(
  self : RouterBuilder[AggregateId, S, C, E],
  command_type : String,
  handlers : Array[@command.CommandHandler[S, C, E]],
) -> RouterBuilder[AggregateId, S, C, E] {
  for handler in handlers {
    self.handlers[command_type] = handler
  }
  self
}

///|
/// 设置默认超时时间(毫秒)
pub fn[AggregateId, S, C, E] RouterBuilder::with_default_timeout(
  self : RouterBuilder[AggregateId, S, C, E],
  timeout_ms : Int64,
) -> RouterBuilder[AggregateId, S, C, E] {
  self.default_config = self.default_config.with_timeout(timeout_ms)
  self
}

///|
/// 设置默认重试次数
pub fn[AggregateId, S, C, E] RouterBuilder::with_default_retries(
  self : RouterBuilder[AggregateId, S, C, E],
  max_retries : Int32,
) -> RouterBuilder[AggregateId, S, C, E] {
  self.default_config = self.default_config.with_retries(max_retries)
  self
}

///|
/// 设置一致性级别
pub fn[AggregateId, S, C, E] RouterBuilder::with_consistency(
  self : RouterBuilder[AggregateId, S, C, E],
  consistency : Consistency,
) -> RouterBuilder[AggregateId, S, C, E] {
  self.default_config = self.default_config.with_consistency(consistency)
  self
}

///|
/// 获取已注册的处理器数量
pub fn[AggregateId, S, C, E] RouterBuilder::handler_count(
  self : RouterBuilder[AggregateId, S, C, E],
) -> Int32 {
  self.handlers.length()
}

///|
pub fn[AggregateId, S, C, E] RouterBuilder::build(
  self : RouterBuilder[AggregateId, S, C, E],
) -> Router[AggregateId, S, C, E] {
  guard self.handler_count() > 0 else { panic() }
  Router::new(self.env, self.default_config, self.handlers)
}

// ============ 命令分发 Reader ============

///|
type DispatchReader[AggregateId, S, E, R] = @monads.Reader[
  RouteEnv[AggregateId, S, E],
  R,
]

///|
/// 创建一个 DispatchReader
pub fn[AggregateId, S, E, R] dispatch_reader_new(
  f : (RouteEnv[AggregateId, S, E]) -> R,
) -> DispatchReader[AggregateId, S, E, R] {
  @monads.Reader::new(f)
}

///|
/// 运行 DispatchReader
pub fn[AggregateId, S, E, R] dispatch_reader_run(
  reader : DispatchReader[AggregateId, S, E, R],
  env : RouteEnv[AggregateId, S, E],
) -> R {
  @monads.Reader::run(reader, env)
}

///|
/// 映射 DispatchReader 的结果
pub fn[AggregateId, S, E, R, A] dispatch_reader_map(
  reader : DispatchReader[AggregateId, S, E, R],
  f : (R) -> A,
) -> DispatchReader[AggregateId, S, E, A] {
  @monads.Reader::map(reader, f)
}

///|
/// 绑定 DispatchReader
pub fn[AggregateId, S, E, R, A] dispatch_reader_bind(
  reader : DispatchReader[AggregateId, S, E, R],
  f : (R) -> DispatchReader[AggregateId, S, E, A],
) -> DispatchReader[AggregateId, S, E, A] {
  @monads.Reader::bind(reader, f)
}

///|
/// 获取环境
pub fn[AggregateId, S, E] dispatch_ask() -> DispatchReader[
  AggregateId,
  S,
  E,
  RouteEnv[AggregateId, S, E],
] {
  @monads.Reader::ask()
}

///|
/// 从环境中提取值
pub fn[AggregateId, S, E, A] dispatch_asks(
  f : (RouteEnv[AggregateId, S, E]) -> A,
) -> DispatchReader[AggregateId, S, E, A] {
  @monads.Reader::asks(f)
}

// ============ 路由器 ============

///|
/// 路由器(类似 Commanded Router)
pub struct Router[AggregateId, S, C, E] {
  // handlers : Map[String, AnyHandler[AggregateId, S, E]]
  env : RouteEnv[AggregateId, S, E]
  default_config : CommandConfig
  handlers : Map[String, @command.CommandHandler[S, C, E]] // 改为 Map,key 为命令类型名
}

///|
pub fn[AggregateId, S, C, E] Router::new(
  env : RouteEnv[AggregateId, S, E],
  default_config : CommandConfig,
  handlers : Map[String, @command.CommandHandler[S, C, E]], // 改为 Map,key 为命令类型名
) -> Router[AggregateId, S, C, E] {
  { handlers, env, default_config, }

  // {
  //   env,
  // }
}

///|
/// 错误回原族(错误穿透不抹平):@store.EventStoreError 变体原样上浮
/// (DuplicateVersion 可分辨),非本族错才降维 StorageError 文本。
fn event_store_error_of(e : Error) -> @store.EventStoreError {
  match e {
    @store.EventStoreError::DuplicateVersion(v) =>
      @store.EventStoreError::DuplicateVersion(v)
    @store.EventStoreError::SerializationError(m) =>
      @store.EventStoreError::SerializationError(m)
    _ => @store.EventStoreError::StorageError(e.to_string())
  }
}

///|
fn snapshot_error_of(e : Error) -> @store.SnapshotError {
  match e {
    @store.SnapshotError::StorageError(m) =>
      @store.SnapshotError::StorageError(m)
    @store.SnapshotError::SerializationError(m) =>
      @store.SnapshotError::SerializationError(m)
    _ => @store.SnapshotError::StorageError(e.to_string())
  }
}

///|
fn event_bus_error_of(e : Error) -> @event.EventBusError {
  match e {
    @event.EventBusError::PublishError(m) =>
      @event.EventBusError::PublishError(m)
    _ => @event.EventBusError::PublishError(e.to_string())
  }
}

///|
/// 单次分发:
/// Step 0 快照基态(快照读路径)→ Step 1 尾事件(after_version =
/// 快照版本)→ Step 2 from_snapshot 重建 → Step 3 执行 → Step 4 append
/// (错误穿透不抹平)→ Step 4.5 EventBus 发布(失败 = Failed
/// 诚实——事件已持久,盲目重试 dispatch 会双重作用,at-least-once 投递
/// 归后续裁定)→ Step 5 快照(每 100 版)→ Step 6 commit。
fn[AggregateId, S, C, E] Router::dispatch_once(
  env : RouteEnv[AggregateId, S, E],
  aggregate_id : AggregateId,
  cmd : @command.CommandMessage[C],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
) -> Result[@aggregate.AggregateRoot[AggregateId, S, C, E], EventSourcingErr] {
  // ========== Step 0: 快照基态 ==========
  let base = (env.snapshot_store.load)(aggregate_id) catch {
    e => return Err(EventSourcingErr::SnapshotErr(snapshot_error_of(e)))
  }
  let (base_state, base_version) = match base {
    Some((state, version)) => (state, version)
    None => (empty_state, 0)
  }
  // ========== Step 1: 加载快照后的尾事件 ==========
  let events = (env.event_store.load)(
    env.event_store,
    aggregate_id,
    base_version,
  ) catch {
    e => return Err(EventSourcingErr::EventStoreErr(event_store_error_of(e)))
  }
  // ========== Step 2: 快照态 + 尾事件重建聚合根 ==========
  let aggregate = @aggregate.AggregateRoot::from_snapshot(
    aggregate_id, empty_state, base_state, base_version, events, handler, applier,
  )
  // ========== Step 3: 执行命令 ==========
  let aggregate = match aggregate.execute(cmd) {
    Ok(agg) => agg
    Err(e) => return Err(EventSourcingErr::CommandErr(e))
  }
  let uncommitted_events = aggregate.uncommitted_events()
  // ========== Step 4: 保存事件(错误穿透)==========
  if !uncommitted_events.is_empty() {
    (env.event_store.append)(env.event_store, aggregate_id, uncommitted_events) catch {
      e => return Err(EventSourcingErr::EventStoreErr(event_store_error_of(e)))
    }
  }
  // ========== Step 4.5: EventBus 发布 ==========
  match env.event_bus {
    Some(bus) =>
      (bus.publish)(bus, uncommitted_events) catch {
        e => return Err(EventSourcingErr::EventBusErr(event_bus_error_of(e)))
      }
    None => ()
  }
  // ========== Step 5: 保存快照(每 100 个事件)==========
  let version = aggregate.version()
  if version > 0 && version % 100 == 0 {
    let snapshot = aggregate.to_snapshot()
    (env.snapshot_store.save)(
      snapshot.aggregate_id,
      snapshot.state,
      snapshot.version,
      snapshot.timestamp,
    ) catch {
      e => return Err(EventSourcingErr::SnapshotErr(snapshot_error_of(e)))
    }
  }
  // ========== Step 6: 提交并返回 ==========
  Ok(aggregate.commit())
}

///|
pub fn[AggregateId, S, C, E] Router::dispatch(
  _self : Router[AggregateId, S, C, E],
  aggregate_id : AggregateId,
  cmd : @command.CommandMessage[C],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
) -> DispatchReader[
  AggregateId,
  S,
  E,
  Result[@aggregate.AggregateRoot[AggregateId, S, C, E], EventSourcingErr],
] {
  dispatch_reader_new(env => {
    Router::dispatch_once(env, aggregate_id, cmd, handler, applier, empty_state)
  })
}

///|
/// 执行命令(直接执行,不返回 Reader)
pub fn[AggregateId, S, C, E] Router::dispatch_now(
  self : Router[AggregateId, S, C, E],
  aggregate_id : AggregateId,
  cmd : @command.CommandMessage[C],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
) -> Result[@aggregate.AggregateRoot[AggregateId, S, C, E], EventSourcingErr] {
  // let reader = self.dispatch_typed(cmd, command_type)
  let reader = self.dispatch(aggregate_id, cmd, handler, applier, empty_state)

  dispatch_reader_run(reader, self.env)
}

///|
/// 带配置的命令分发(重试裁决走 Effect 协议):
/// **max_retries 生效** = Duplicate 族乐观并发重试(重载→重执行→重追加,
/// ES 正统重试语义——命令对最新态重新裁决),裁决走 RetryMachine 记录面
/// (effect_kind_of_sourcing_err 分类 + 机器 decide 上限门——分类/动作/上限
/// 全机器面,与 aggregate/effect 协议同源);**timeout_ms 降级声明** = MVP
/// 同步径无定时器,退避时长同步径忽略(WaitRetry → 立即重试),随 async
/// dispatch 面另役。dispatch_with_config 与 dispatch 的差别仅此。
pub fn[AggregateId, S, C, E] Router::dispatch_with_config(
  self : Router[AggregateId, S, C, E],
  aggregate_id : AggregateId,
  cmd : @command.CommandMessage[C],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
  timeout_ms : Int64,
  max_retries : Int32,
) -> DispatchReader[
  AggregateId,
  S,
  E,
  Result[@aggregate.AggregateRoot[AggregateId, S, C, E], EventSourcingErr],
] {
  ignore(timeout_ms)
  ignore(self)
  let machine = Router::store_retry_machine(max_retries)
  dispatch_reader_new(env => {
    Router::dispatch_with_retry(
      env, aggregate_id, cmd, handler, applier, empty_state, machine,
    )
  })
}

///|
/// 总错误分类(Effect 协议结构知识面——分类固定非裁决):
/// 命令/存储族各归各分类器;快照故障归 Storage;聚合 id 解析形归 Other。
pub fn effect_kind_of_sourcing_err(
  err : EventSourcingErr,
) -> @aggregate.EffectErrorKind {
  match err {
    CommandErr(e) => @aggregate.effect_kind_of_command_error(e)
    EventStoreErr(e) => @aggregate.effect_kind_of_store_error(e)
    SnapshotErr(_) => @aggregate.Storage
    EventBusErr(_) => @aggregate.Storage
    ConsistencyErr(_) => @aggregate.Other
    AggregateErr(_) => @aggregate.Other
  }
}

///|
/// 分发重试机(router 径词表:Duplicate 族 retry,余 exhausted;上限 =
/// max_retries;WaitRetry(0) = 同步径立即重试,退避随 async 面接入)
fn Router::store_retry_machine(max_retries : Int32) -> @aggregate.RetryMachine {
  {
    default_action: fn(kind) {
      match kind {
        @aggregate.Duplicate => @aggregate.ActionRetry
        _ => @aggregate.ActionExhausted
      }
    },
    decide: fn(attempt, _failures, _kind) {
      if attempt > max_retries {
        @aggregate.GiveUpRaise
      } else {
        @aggregate.WaitRetry(wait_ms=0L)
      }
    },
  }
}

///|
/// 乐观并发重试循环(协议形:分类 → 机器默认分派 → decide 门;
/// 无手写错误硬匹配。WaitRetry 同步径立即重试——退避时长随 async 面接入)
fn[AggregateId, S, C, E] Router::dispatch_with_retry(
  env : RouteEnv[AggregateId, S, E],
  aggregate_id : AggregateId,
  cmd : @command.CommandMessage[C],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
  machine : @aggregate.RetryMachine,
) -> Result[@aggregate.AggregateRoot[AggregateId, S, C, E], EventSourcingErr] {
  let mut attempts = 0
  let mut consecutive_failures = 0
  let mut result = Router::dispatch_once(
    env, aggregate_id, cmd, handler, applier, empty_state,
  )
  let mut running = result is Err(_)
  while running {
    let err = match result {
      Err(e) => e
      Ok(_) => return result
    }
    consecutive_failures += 1
    let kind = effect_kind_of_sourcing_err(err)
    match (machine.default_action)(kind) {
      @aggregate.ActionExhausted => {
        running = false
        return Err(err)
      }
      @aggregate.ActionRetry => {
        attempts += 1
        match (machine.decide)(attempts, consecutive_failures, kind) {
          @aggregate.WaitRetry(_) =>
            result = Router::dispatch_once(
              env, aggregate_id, cmd, handler, applier, empty_state,
            )
          @aggregate.GiveUpRaise => {
            running = false
            return Err(err)
          }
        }
      }
    }
  }
  result
}

///|
/// 所有命令要么全部成功,要么全部失败
pub fn[AggregateId, S, C, E] Router::dispatch_batch(
  self : Router[AggregateId, S, C, E],
  commands : Array[(AggregateId, @command.CommandMessage[C])],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
) -> DispatchReader[
  AggregateId,
  S,
  E,
  Result[
    Array[@aggregate.AggregateRoot[AggregateId, S, C, E]],
    EventSourcingErr,
  ],
] {
  dispatch_reader_new(fn(env) {
    let results : Array[@aggregate.AggregateRoot[AggregateId, S, C, E]] = []
    for item in commands {
      let id = item.0
      let cmd = item.1
      let reader = self.dispatch(id, cmd, handler, applier, empty_state)
      match dispatch_reader_run(reader, env) {
        Ok(aggregate) => results.push(aggregate)
        Err(e) => return Err(e)
      }
    }
    Ok(results)
  })
}

// pub fn[AggregateId, S, C, E] Router::dispatch_batch_parallel(
//   self : Router[AggregateId, S, C, E],
//   commands : Array[(AggregateId, @command.CommandMessage[C])],
//   handler : @command.CommandHandler[S, C, E],
//   applier : @event.EventApplier[S, E],
//   empty_state : S,
// ) -> DispatchReader[
//   AggregateId,
//   S,
//   E,
//   Result[Array[@aggregate.AggregateRoot[AggregateId, S, C, E]], EventSourcingErr],
// ] {
//   @monads.Reader::new_async(async fn(env) raise {
//     let results = Ref::new(Array::new())
//     let errors = Ref::new(Array::new())

//     ignore(@async.with_task_group( fn(tg)  {
//       for item in commands {
//         let id = item.0
//         let cmd = item.1
//         let env_clone = env

//         ignore(tg.spawn( fn ()  {
//           let reader = self.dispatch(id, cmd, handler, applier, empty_state)
//           match dispatch_reader_run(reader, env_clone) {
//             Ok(aggregate) => results.update(fn(arr) { 
//               arr.push(aggregate)
//               arr
//             })
//             Err(e) => errors.update(fn(arr) {
//               arr.push(e)
//               arr
//             })
//           }
//         }))
//       }
//     }))

//     // 等待所有任务完成
//     let error_arr = errors.val
//     if !error_arr.is_empty() {
//       Err(error_arr[0])
//     } else {
//       Ok(results.val)
//     }
//   })
// }

///|
/// 如果只注册了一个处理器,可以直接使用此方法
pub fn[AggregateId, S, C, E] Router::dispatch_default(
  self : Router[AggregateId, S, C, E],
  aggregate_id : AggregateId,
  cmd : @command.CommandMessage[C],
  applier : @event.EventApplier[S, E],
  empty_state : S,
) -> Result[@aggregate.AggregateRoot[AggregateId, S, C, E], EventSourcingErr] {
  if self.handlers.is_empty() {
    return Err(
      EventSourcingErr::CommandErr(
        @command.CommandError::UnregisteredCommand("No handlers registered"),
      ),
    )
  }

  // 使用第一个注册的处理器
  // 使用第一个注册的处理器
  let handler = match self.handlers.iter().next() {
    Some((_, h)) => h
    None =>
      return Err(
        EventSourcingErr::CommandErr(
          @command.CommandError::UnregisteredCommand("No handlers registered"),
        ),
      )
  }
  self.dispatch_now(aggregate_id, cmd, handler, applier, empty_state)
}

///|

// ============ 辅助类型 ============

///|
pub(all) enum Consistency {
  Eventual
  Strong
}