// DDD 聚合根 ProcessInstance + 子实体 ProcessTask —— 移植自 rust model.rs L168-L542
// ⚠️ MoonBit 记录为引用语义:mut 字段原地共享可变;显式 clone 点用 clone_* 函数。
// content 用 String(JSON 文本)承载(rust 为 Vec,DB BLOB 边界在仓储层处理)。

///|
pub(all) struct ProcessDefine {
  mut id : Int64
  name : String
  display_name : String
  define_type : String
  mut state : Int
  mut content : String
  mut version : Int
  mut create_time : String?
  mut create_user : String?
  mut update_time : String?
  mut update_user : String?
} derive(Eq)

///|
pub fn ProcessDefine::clone(self : ProcessDefine) -> ProcessDefine {
  { ..self }
}

///|
/// ProcessInstance —— DDD 聚合根
pub(all) struct ProcessInstance {
  mut instance_id : Int64
  mut parent_id : Int64?
  mut define_id : Int64
  mut state : Int
  mut parent_node_name : String?
  mut business_no : String?
  mut operator : String
  mut expire_time : String?
  mut variables : @json.FlowData
  mut tasks : Array[ProcessTask]
  mut create_time : String?
  mut create_user : String?
  mut update_time : String?
  mut update_user : String?
  // 瞬态:define 信息(不落实例表)
  mut define : ProcessDefine?
}

///|
pub fn ProcessInstance::clone(self : ProcessInstance) -> ProcessInstance {
  {
    instance_id: self.instance_id,
    parent_id: self.parent_id,
    define_id: self.define_id,
    state: self.state,
    parent_node_name: self.parent_node_name,
    business_no: self.business_no,
    operator: self.operator,
    expire_time: self.expire_time,
    variables: @json.FlowData::from_map(clone_json_map(self.variables.inner())),
    tasks: self.tasks.map(fn(t) { t.clone() }),
    create_time: self.create_time,
    create_user: self.create_user,
    update_time: self.update_time,
    update_user: self.update_user,
    define: match self.define {
      Some(d) => Some(d.clone())
      None => None
    },
  }
}

///|
fn clone_json_map(src : Map[String, Json]) -> Map[String, Json] {
  let m : Map[String, Json] = Map::new()
  for k, v in src {
    m[k] = v
  }
  m
}

///|
/// 工厂:新建实例(state=DOING=10)
pub fn ProcessInstance::create(
  define : ProcessDefine,
  operator : String,
  args : @json.FlowData
) -> ProcessInstance {
  let variables = @json.FlowData::new()
  variables.merge(args)
  {
    instance_id: 0L,
    parent_id: None,
    define_id: define.id,
    state: InstanceState::Doing.code(),
    parent_node_name: None,
    business_no: args.get_str("BUSINESS_NO"),
    operator,
    expire_time: None,
    variables,
    tasks: [],
    create_time: Some(current_time_str()),
    create_user: Some(operator),
    update_time: None,
    update_user: None,
    define: Some(define.clone()),
  }
}

///|
/// 工厂(子流程):带父实例
pub fn ProcessInstance::create_with_parent(
  define : ProcessDefine,
  operator : String,
  args : @json.FlowData,
  parent_id : Int64,
  parent_node_name : String
) -> ProcessInstance {
  let inst = ProcessInstance::create(define, operator, args)
  inst.parent_id = Some(parent_id)
  inst.parent_node_name = Some(parent_node_name)
  inst
}

///|
/// 完成任务:finish 任务 + 合并 f_ 变量(rust complete_task)
pub fn ProcessInstance::complete_task(
  self : ProcessInstance,
  task_id : Int64,
  operator : String,
  args : @json.FlowData
) -> Unit raise @error.JeeflowError {
  let mut found : ProcessTask? = None
  for t in self.tasks {
    if t.task_id == task_id {
      found = Some(t)
    }
  }
  let task = match found {
    Some(t) => t
    None =>
      raise @error.InstanceNotFound(
        task_id,
      ) // rust 语义:任务不在聚合内报错;消息对齐 "任务不存在"
  }
  for k, v in args.inner() {
    if k.starts_with("f_") {
      self.variables.insert(k, v)
    }
  }
  task.finish(operator)
}

///|
pub fn ProcessInstance::abandon_task(
  self : ProcessInstance,
  task_id : Int64
) -> Unit raise @error.JeeflowError {
  let mut found : ProcessTask? = None
  for t in self.tasks {
    if t.task_id == task_id {
      found = Some(t)
    }
  }
  match found {
    Some(t) => {
      t.abandon()
      self.state = InstanceState::Abandon.code()
    }
    None => raise @error.TaskNotFound(task_id)
  }
}

///|
pub fn ProcessInstance::abandon_all_doing(self : ProcessInstance) -> Unit {
  for t in self.tasks {
    if t.task_state == TaskState::Doing.code() {
      try {
        t.abandon()
      } catch {
        _ => ()
      }
    }
  }
}

///|
pub fn ProcessInstance::finish(self : ProcessInstance) -> Unit {
  self.state = InstanceState::Finished.code()
}

///|
pub fn ProcessInstance::reject(self : ProcessInstance) -> Unit {
  self.state = InstanceState::Reject.code()
}

///|
pub fn ProcessInstance::interrupt(self : ProcessInstance) -> Unit {
  for t in self.tasks {
    if t.task_state == TaskState::Doing.code() {
      try {
        t.interrupt()
      } catch {
        _ => ()
      }
    }
  }
  self.state = InstanceState::Interrupt.code()
}

///|
pub fn ProcessInstance::resume(self : ProcessInstance) -> Unit {
  for t in self.tasks {
    if t.task_state == TaskState::Interrupt.code() {
      t.task_state = TaskState::Doing.code()
    }
  }
  self.state = InstanceState::Doing.code()
}

///|
pub fn ProcessInstance::pending(self : ProcessInstance) -> Unit {
  for t in self.tasks {
    if t.task_state == TaskState::Doing.code() {
      try {
        t.pending()
      } catch {
        _ => ()
      }
    }
  }
  self.state = InstanceState::Pending.code()
}

///|
/// 撤回:实例 30 WITHDRAW + 全部 DOING 任务 30(C28:任务 30 非 45)
pub fn ProcessInstance::withdraw(self : ProcessInstance) -> Unit {
  for t in self.tasks {
    if t.task_state == TaskState::Doing.code() {
      t.withdraw()
    }
  }
  self.state = InstanceState::Withdraw.code()
}

///|
pub fn ProcessInstance::add_variable(self : ProcessInstance, args : @json.FlowData) -> Unit {
  self.variables.merge(args)
}

///|
pub fn ProcessInstance::remove_variables(self : ProcessInstance, keys : Array[String]) -> Unit {
  for k in keys {
    self.variables.remove(k) |> ignore
  }
}

///|
/// 建任务(子实体工厂;task_id=0 由 ID 生成器赋值——rust 91b:原片赋 id 再克隆返回)
pub fn ProcessInstance::create_task(
  self : ProcessInstance,
  task_name : String,
  display_name : String,
  actor_ids : Array[String],
  operator : String,
  task_type : TaskType,
  perform_type : PerformType,
  form_key : String?,
  parent_task_id : Int64?
) -> ProcessTask {
  let task : ProcessTask = {
    task_id: 0L,
    process_instance_id: self.instance_id,
    task_name,
    display_name,
    task_type: task_type.code(),
    perform_type: perform_type.code(),
    task_state: TaskState::Doing.code(),
    actor_id: None,
    actor_ids: actor_ids.copy(),
    finish_time: None,
    expire_time: None,
    form_key,
    parent_task_id,
    variables: @json.FlowData::new(),
    create_time: Some(current_time_str()),
    create_user: Some(operator),
    update_time: None,
    update_user: None,
  }
  self.tasks.push(task)
  task
}

///|
/// 会签任务:每人一个独立任务(C9:串行一次只建一个由引擎控制;此处为并行建全入口)
pub fn ProcessInstance::create_countersign_tasks(
  self : ProcessInstance,
  task_name : String,
  display_name : String,
  actor_ids : Array[String],
  operator : String,
  task_type : TaskType,
  form_key : String?,
  parent_task_id : Int64?
) -> Array[ProcessTask] {
  let out : Array[ProcessTask] = []
  for actor in actor_ids {
    out.push(
      self.create_task(
        task_name,
        display_name,
        [actor],
        operator,
        task_type,
        Countersign,
        form_key,
        parent_task_id,
      ),
    )
  }
  out
}

///|
/// 历史任务(custom 节点用,直接 FINISHED)
pub fn ProcessInstance::create_history_task(
  self : ProcessInstance,
  task_name : String,
  display_name : String,
  operator : String,
  task_type : TaskType
) -> ProcessTask {
  let task = self.create_task(
    task_name,
    display_name,
    [operator],
    operator,
    task_type,
    Normal,
    None,
    None,
  )
  task.task_state = TaskState::Finished.code()
  task.actor_id = Some(operator)
  task
}

///|
/// 退回上一步:为新节点建待办任务
pub fn ProcessInstance::reject_task(
  self : ProcessInstance,
  task_name : String,
  display_name : String,
  actor_ids : Array[String],
  operator : String,
  parent_task_id : Int64
) -> ProcessTask {
  self.create_task(
    task_name,
    display_name,
    actor_ids,
    operator,
    Major,
    Normal,
    None,
    Some(parent_task_id),
  )
}

///|
pub fn ProcessInstance::get_doing_tasks(self : ProcessInstance) -> Array[ProcessTask] {
  let out : Array[ProcessTask] = []
  for t in self.tasks {
    if t.task_state == TaskState::Doing.code() {
      out.push(t)
    }
  }
  out
}

///|
pub fn ProcessInstance::get_doing_tasks_by_names(
  self : ProcessInstance,
  names : Array[String]
) -> Array[ProcessTask] {
  let out : Array[ProcessTask] = []
  for t in self.tasks {
    if t.task_state == TaskState::Doing.code() && names.contains(t.task_name) {
      out.push(t)
    }
  }
  out
}

///|
pub fn ProcessInstance::get_finished_tasks(self : ProcessInstance) -> Array[ProcessTask] {
  let out : Array[ProcessTask] = []
  for t in self.tasks {
    if t.task_state == TaskState::Finished.code() {
      out.push(t)
    }
  }
  out
}

///|
pub fn ProcessInstance::get_done_tasks_by_names(
  self : ProcessInstance,
  names : Array[String]
) -> Array[ProcessTask] {
  let out : Array[ProcessTask] = []
  for t in self.tasks {
    if t.task_state == TaskState::Finished.code() && names.contains(t.task_name) {
      out.push(t)
    }
  }
  out
}

///|
pub fn ProcessInstance::get_history_tasks(self : ProcessInstance) -> Array[ProcessTask] {
  self.tasks.copy()
}

///|
pub fn ProcessInstance::is_all_tasks_finished(self : ProcessInstance) -> Bool {
  let mut any_doing = false
  for t in self.tasks {
    if t.task_state == TaskState::Doing.code() {
      any_doing = true
    }
  }
  not(any_doing)
}

///|
pub fn ProcessInstance::is_doing(self : ProcessInstance) -> Bool {
  self.state == InstanceState::Doing.code()
}

///|
pub fn ProcessInstance::is_finished(self : ProcessInstance) -> Bool {
  self.state == InstanceState::Finished.code()
}

///|
/// ProcessTask —— 子实体
pub(all) struct ProcessTask {
  mut task_id : Int64
  mut process_instance_id : Int64
  mut task_name : String
  mut display_name : String
  mut task_type : Int
  mut perform_type : Int
  mut task_state : Int
  mut actor_id : String?
  mut actor_ids : Array[String]
  mut finish_time : String?
  mut expire_time : String?
  mut form_key : String?
  mut parent_task_id : Int64?
  mut variables : @json.FlowData
  mut create_time : String?
  mut create_user : String?
  mut update_time : String?
  mut update_user : String?
}

///|
pub fn ProcessTask::clone(self : ProcessTask) -> ProcessTask {
  {
    task_id: self.task_id,
    process_instance_id: self.process_instance_id,
    task_name: self.task_name,
    display_name: self.display_name,
    task_type: self.task_type,
    perform_type: self.perform_type,
    task_state: self.task_state,
    actor_id: self.actor_id,
    actor_ids: self.actor_ids.copy(),
    finish_time: self.finish_time,
    expire_time: self.expire_time,
    form_key: self.form_key,
    parent_task_id: self.parent_task_id,
    variables: @json.FlowData::from_map(clone_json_map(self.variables.inner())),
    create_time: self.create_time,
    create_user: self.create_user,
    update_time: self.update_time,
    update_user: self.update_user,
  }
}

///|
/// 完成(state→FINISHED=20);守卫:仅 DOING + 处理人可办(并发语义 §6.2)
pub fn ProcessTask::finish(self : ProcessTask, operator : String) -> Unit raise @error.JeeflowError {
  if self.task_state != TaskState::Doing.code() {
    raise @error.InvalidState("Task \{self.task_id} is not in DOING state (current=\{self.task_state})")
  }
  if not(self.is_allowed(operator)) {
    raise @error.PermissionDenied("Operator \{operator} is not allowed on task \{self.task_id}")
  }
  self.task_state = TaskState::Finished.code()
  self.actor_id = Some(operator)
  self.finish_time = Some(current_time_str())
}

///|
pub fn ProcessTask::abandon(self : ProcessTask) -> Unit raise @error.JeeflowError {
  if self.task_state != TaskState::Doing.code() {
    raise @error.InvalidState("Task \{self.task_id} is not in DOING state")
  }
  self.task_state = TaskState::Abandon.code()
}

///|
pub fn ProcessTask::withdraw(self : ProcessTask) -> Unit {
  self.task_state = TaskState::Withdraw.code()
}

///|
pub fn ProcessTask::interrupt(self : ProcessTask) -> Unit raise @error.JeeflowError {
  if self.task_state != TaskState::Doing.code() {
    raise @error.InvalidState("Task \{self.task_id} is not in DOING state")
  }
  self.task_state = TaskState::Interrupt.code()
}

///|
pub fn ProcessTask::pending(self : ProcessTask) -> Unit raise @error.JeeflowError {
  if self.task_state != TaskState::Doing.code() {
    raise @error.InvalidState("Task \{self.task_id} is not in DOING state")
  }
  self.task_state = TaskState::Pending.code()
}

///|
pub fn ProcessTask::resume(self : ProcessTask) -> Unit {
  if self.task_state == TaskState::Interrupt.code() {
    self.task_state = TaskState::Doing.code()
  }
}

///|
/// 处理人校验:"flow.auto"/"flow.admin" 直通
pub fn ProcessTask::is_allowed(self : ProcessTask, operator : String) -> Bool {
  if operator == "flow.auto" || operator == "flow.admin" {
    return true
  }
  self.is_doing() && self.actor_ids.contains(operator)
}

///|
pub fn ProcessTask::is_doing(self : ProcessTask) -> Bool {
  self.task_state == TaskState::Doing.code()
}

///|
pub fn ProcessTask::is_finished(self : ProcessTask) -> Bool {
  self.task_state == TaskState::Finished.code()
}