/// FIST-Mbt engine: 指挥-执行-验收 完整业务层。
/// 迁移自 FIST(Python) 的 flow (publish→plan→dispatch→claim→execute→submit→verify→complete→archive)。

/// 根任务 id
pub fn root_task_id() -> String { "T0" }

/// 核心引擎:持有 store,暴露指挥-执行-验收完整闭环。
/// store 为后端路由(内存 / SQLite),业务逻辑不感知具体实现。
pub struct FistEngine {
  store : StoreBackend
}

pub fn FistEngine::new(store~ : StoreBackend = StoreBackend::Mem(MemoryStore::new())) -> FistEngine {
  { store, }
}

/// 以指定 SQLite 数据库打开持久化引擎(内建数据库入口;失败返回 None 供调用方回退)。
pub fn FistEngine::open_sqlite(db_path : String) -> Option[FistEngine] {
  match SqliteStore::open(db_path) {
    None => None
    Some(s) => Some(FistEngine::new(store=StoreBackend::Sql(s)))
  }
}

/// 发布根任务(仅限人类指挥官)
pub fn FistEngine::publish(
  self : FistEngine,
  project_dir~ : String,
  description~ : String,
  created_by~ : String,
  now~ : String,
) -> Result[String, String] {
  if created_by != "human_steward" && created_by != "human" {
    return Err("publish 仅限人类指挥官(created_by=human_steward)")
  }
  let id = root_task_id()
  let t = Task::new(
    id=id,
    project_dir~,
    description~,
    depth=3,
    split_n=3,
    created_at=now,
  )
  match self.store.create_task(t) {
    Ok(_) => Ok(id)
    Err(e) => Err(e)
  }
}

/// 对指定任务生成子任务树(一层)。非原子任务才可拆分。
/// 返回生成的子任务 id 列表。
pub fn FistEngine::plan(
  self : FistEngine,
  task_id~ : String,
  split_n~ : Int = 3,
  by~ : String,
  now~ : String,
) -> Result[Array[String], String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(parent) => {
      if parent.is_leaf() {
        return Err("原子任务不可再拆分: \{task_id}")
      }
      let st = parent.get_status()
      if st != Claimed && st != Pending && st != Splitting {
        return Err("非法拆分: 任务处于 [\{parent.status_to_string()}]")
      }
      // 标记父任务进入拆分中
      match parent.split() {
        Ok(p2) => ignore(self.store.update_task(p2))
        Err(e) => return Err(e)
      }
      let child_depth = parent.get_depth() - 1
      let children : Array[String] = []
      for i = 1; i <= split_n; i = i + 1 {
        let cid = child_id(parent_id=task_id, idx=i)
        let child = Task::new(
          id=cid,
          project_dir=parent.project_dir,
          description="\{task_id} 的子任务 \{i}",
          parent_id=task_id,
          priority=parent.priority,
          importance=parent.importance,
          depth=child_depth,
          split_n=child_depth,
          created_at=now,
        )
        match self.store.create_task(child) {
          Ok(_) => children.push(cid)
          Err(e) => return Err(e)
        }
      }
      Ok(children)
    }
  }
}

/// 认领任务(executor 认领,待领取 -> 已领取 -> 执行中)
pub fn FistEngine::claim(
  self : FistEngine,
  task_id~ : String,
  assignee~ : String,
  now~ : String,
) -> Result[Task, String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) => {
      let c = match t.claim(assignee~) {
        Ok(x) => x
        Err(e) => return Err(e)
      }
      // claim 仅迁移 待领取 -> 已领取;由 execute 进入执行中,保证已领取态可被 plan 拆分
      let c3 = { ..c, updated_at: now, }
      ignore(self.store.update_task(c3))
      Ok(c3)
    }
  }
}

/// 记录执行交付物
pub fn FistEngine::execute(
  self : FistEngine,
  task_id~ : String,
  deliverable~ : String,
  now~ : String,
) -> Result[Task, String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) => {
      let st = t.get_status()
      if st != Executing && st != Splitting && st != Claimed {
        return Err("非法执行: 任务处于 [\{t.status_to_string()}]")
      }
      let c = match t.execute() {
        Ok(x) => x
        Err(_) => t
      }
      let c2 = { ..c, deliverable, updated_at: now, }
      ignore(self.store.update_task(c2))
      Ok(c2)
    }
  }
}

/// 提交验收(执行中 -> 待验收)
pub fn FistEngine::submit(
  self : FistEngine,
  task_id~ : String,
  now~ : String,
) -> Result[Task, String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) => {
      let c = match t.submit() {
        Ok(x) => x
        Err(e) => return Err(e)
      }
      let c2 = { ..c, updated_at: now, }
      ignore(self.store.update_task(c2))
      Ok(c2)
    }
  }
}

/// 列出某任务的所有直接子任务
pub fn FistEngine::children_of(self : FistEngine, task_id : String) -> Array[Task] {
  let out : Array[Task] = []
  for t in self.store.list_tasks() {
    match t.get_parent() {
      Some(p) => if p == task_id { out.push(t) }
      None => ()
    }
  }
  out
}

/// 是否为「非叶节点且所有直接子任务都已完成」
pub fn FistEngine::all_subtasks_completed(
  self : FistEngine,
  parent : Task,
) -> Bool {
  let children = self.children_of(parent.get_id())
  if children.is_empty() { return false }
  children.all(fn(t) { t.get_status() == Completed })
}

/// 验收(verifier):Reviewing -> Completed;若因此父任务全部子任务完成,则父任务自动待验收。
pub fn FistEngine::verify(
  self : FistEngine,
  task_id~ : String,
  verifier~ : String,
  now~ : String,
) -> Result[Task, String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) => {
      if t.get_status() != Reviewing {
        return Err("非法验收: 任务处于 [\{t.status_to_string()}],需先 submit")
      }
      let c = match t.complete(completed_by=verifier) {
        Ok(x) => x
        Err(e) => return Err(e)
      }
      let c2 = { ..c, updated_at: now, }
      ignore(self.store.update_task(c2))
      // 向上归并:父任务全部子任务完成后自动待验收
      match c2.get_parent() {
        Some(pid) =>
          match self.store.get_task(pid) {
            Some(parent) =>
              if self.all_subtasks_completed(parent) {
                let pe = match parent.execute() {
                  Ok(x) => x
                  Err(_) => parent
                }
                match pe.submit() {
                  Ok(p2) => {
                    ignore(self.store.update_task({ ..p2, updated_at: now, }))
                    Ok(c2)
                  }
                  Err(e) => Err(e)
                }
              } else {
                Ok(c2)
              }
            None => Ok(c2)
          }
        None => Ok(c2)
      }
    }
  }
}

/// 人类确认归档:Completed -> Archived(仅限人类指挥官)
pub fn FistEngine::archive(
  self : FistEngine,
  task_id~ : String,
  by~ : String,
  now~ : String,
) -> Result[Task, String] {
  if by != "human_steward" && by != "human" {
    return Err("archive 仅限人类指挥官")
  }
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) => {
      let c = match t.archive() {
        Ok(x) => x
        Err(e) =>
          // 未完成则先核验通过再归档
          match t.complete(completed_by=by) {
            Ok(c1) =>
              match c1.archive() {
                Ok(c2) => c2
                Err(e2) => return Err(e2)
              }
            Err(e2) => return Err(e2)
          }
      }
      let c2 = { ..c, updated_at: now, }
      ignore(self.store.update_task(c2))
      Ok(c2)
    }
  }
}

/// 列出全部任务
pub fn FistEngine::list_all(self : FistEngine) -> Array[Task] {
  self.store.list_tasks()
}

/// 按状态过滤列出
pub fn FistEngine::list_by_status(
  self : FistEngine,
  status : TaskStatus,
) -> Array[Task] {
  self.store.list_tasks().filter(fn(t) { t.get_status() == status })
}

/// 查询单个任务
pub fn FistEngine::get_task(self : FistEngine, task_id : String) -> Option[Task] {
  self.store.get_task(task_id)
}

/// 回滚/重派:任意非归档任务 -> 已领取(M4 heal watchdog 用)。返回回滚后的任务。
pub fn FistEngine::reopen_task(
  self : FistEngine,
  task_id : String,
  now : String,
) -> Result[Task, String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) => {
      let c = match t.reopen() {
        Ok(x) => x
        Err(e) => return Err(e)
      }
      let c2 = { ..c, updated_at: now, }
      ignore(self.store.update_task(c2))
      Ok(c2)
    }
  }
}

/// 删除任务(仅限已归档,ARCHIVING 清理)
pub fn FistEngine::delete_task(self : FistEngine, task_id : String) -> Result[Unit, String] {
  match self.store.get_task(task_id) {
    None => Err("task not found: \{task_id}")
    Some(t) =>
      if t.get_status() == Archived {
        self.store.delete_task(task_id)
      } else {
        Err("仅已归档任务可删除(当前 [\{t.status_to_string()}])")
      }
  }
}