// aggregate.mbt
//! 聚合根实现

///|
/// 聚合根状态
pub struct AggregateState[AggregateId, S, E] {
  state : S
  version : Int32
  uncommitted_events : Array[@event.EventMessage[AggregateId, E]]
}

///|
/// 命令处理程序类型
// pub type @command.CommandHandler[S, C, E] = (S, C) -> Result[Array[E], @command.CommandError]
// pub type @event.EventApplier[S,E] = (S, E) -> S

///|
/// 聚合根
pub struct AggregateRoot[AggregateId, S, C, E] {
  handler : @command.CommandHandler[S, C, E]
  applier : @event.EventApplier[S, E]
  empty_state : S
  mut state : AggregateState[AggregateId, S, E]
  id : AggregateId
}
/// 聚合根数据结构
// pub struct AggregateRoot[Id, S, E] {
//   id : Id
//   state : S
//   version : Int
//   uncommitted_events : Array[E]
// }
// impl[Id, S,C,E] AggregateRoot[Id, S,C,E] {

///|
/// 创建新的聚合根
pub fn[AggregateId, S, C, E] AggregateRoot::new(
  id : AggregateId,
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
) -> AggregateRoot[AggregateId, S, C, E] {
  {
    handler,
    applier,
    empty_state,
    state: { state: empty_state, version: 0, uncommitted_events: [], },
    id,
  }
}

///|
/// 从已保存的事件恢复
pub fn[AggregateId, S, C, E] AggregateRoot::from_events(
  id : AggregateId,
  events : Array[@event.EventMessage[AggregateId, E]],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
  empty_state : S,
) -> AggregateRoot[AggregateId, S, C, E] {
  AggregateRoot::from_snapshot(
    id, empty_state, empty_state, 0, events, handler, applier,
  )
}

///|
/// 从快照基态 + 尾事件恢复(快照读路径):base = 快照态/版本,尾事件
/// 折入;尾空 = 版本取快照版本(非 0)。from_events = 本形特例
/// (base = 空态/0,委托)。
pub fn[AggregateId, S, C, E] AggregateRoot::from_snapshot(
  id : AggregateId,
  empty_state : S,
  base_state : S,
  base_version : Int32,
  events : Array[@event.EventMessage[AggregateId, E]],
  handler : @command.CommandHandler[S, C, E],
  applier : @event.EventApplier[S, E],
) -> AggregateRoot[AggregateId, S, C, E] {
  let final_state = events.fold(init=base_state, fn(s, e) {
    match applier {
      @event.EventApplier::Single(f) => f(s, e.event)
      @event.EventApplier::Batch(f) => f(s, [e.event])
    }
  })
  let version = match events.last() {
    Some(last) => last.aggregate_version
    None => base_version
  }
  {
    handler,
    applier,
    empty_state,
    state: { state: final_state, version, uncommitted_events: [], },
    id,
  }
}

///|
/// 执行命令(借鉴 Commanded 的 execute/apply 模式)
pub fn[AggregateId, S, C, E] AggregateRoot::execute(
  self : AggregateRoot[AggregateId, S, C, E],
  cmd : @command.CommandMessage[C],
) -> Result[AggregateRoot[AggregateId, S, C, E], @command.CommandError] {
  // 1. Execute: 业务校验,产生事件
  match (self.handler)(self.state.state, cmd.command) {
    Ok(events) => {
      // 2. Apply: 应用事件到状态
      let mut current_state = self.state.state
      let mut current_version = self.state.version

      let event_messages : Array[@event.EventMessage[AggregateId, E]] = []

      for event in events {
        current_version += 1
        let event_msg = @event.EventMessage::from_command(
          event,
          self.id,
          current_version,
          cmd,
        )
        event_messages.push(event_msg)
        current_state = match self.applier {
          @event.EventApplier::Single(f) => f(current_state, event)
          @event.EventApplier::Batch(f) => f(current_state, [event])
        }
      }

      // 3. 更新聚合状态
      self.state = {
        state: current_state,
        version: current_version,
        uncommitted_events: self.state.uncommitted_events + event_messages,
      }

      Ok(self)
    }
    Err(err) => Err(err)
  }
}

///|
/// 提交事件(清空未提交事件)
pub fn[AggregateId, S, C, E] AggregateRoot::commit(
  self : AggregateRoot[AggregateId, S, C, E],
) -> AggregateRoot[AggregateId, S, C, E] {
  self.state = {
    state: self.state.state,
    version: self.state.version,
    uncommitted_events: [],
  }
  self
}

///|
/// 获取未提交事件
pub fn[AggregateId, S, C, E] AggregateRoot::uncommitted_events(
  self : AggregateRoot[AggregateId, S, C, E],
) -> Array[@event.EventMessage[AggregateId, E]] {
  self.state.uncommitted_events
}

///|
/// 获取当前版本
pub fn[AggregateId, S, C, E] AggregateRoot::version(
  self : AggregateRoot[AggregateId, S, C, E],
) -> Int32 {
  self.state.version
}

///|
/// 获取状态
pub fn[AggregateId, S, C, E] AggregateRoot::current_state(
  self : AggregateRoot[AggregateId, S, C, E],
) -> S {
  self.state.state
}

///|
/// 创建快照
pub fn[AggregateId, S, C, E] AggregateRoot::to_snapshot(
  self : AggregateRoot[AggregateId, S, C, E],
) -> @store.Snapshot[AggregateId, S] {
  @store.Snapshot::new(self.id, self.state.state, self.state.version)
}
// }

///|
/// 形态 A 流式执行:命令自动包装 CommandMessage,
/// 错误 raise 上抛,返回 Self 链式。
/// 用法:root.exec(CreateAccount("main", 100)).exec(DepositMoney(50))
pub fn[AggregateId, S, C, E] AggregateRoot::exec(
  self : AggregateRoot[AggregateId, S, C, E],
  cmd : C,
) -> AggregateRoot[AggregateId, S, C, E] raise @command.CommandError {
  let msg = @command.CommandMessage::new(cmd)
  match self.execute(msg) {
    Ok(agg) => agg
    Err(e) => raise e
  }
}