/// store/specs.mbt — specs 表 schema + CRUD(Omega 强验证语料账本)。
///
/// 表结构沿用 store_sqlite.mbt create_schema 中的既有定义(Phase 2 预置骨架),
/// 本文件把它升级为真正可读写的语料账本:
///   specs (id TEXT PRIMARY KEY, task_id, spec_type, content, status, created_at, updated_at)
///
/// 约定:
///   spec_type = "spec"       执行前语料(语料创建者编写、验证者审核)
///   spec_type = "result"     成果复验记录(验证者对执行成果的复验)
///   spec_type = "escalation" 打回超限升级记录(转人工)
///   status    ∈ pending / approved / rejected / escalated

///|
/// specs 表 CREATE TABLE SQL(幂等,兼容旧库)。
pub fn specs_table_sql() -> String {
  "CREATE TABLE IF NOT EXISTS specs (id TEXT PRIMARY KEY, task_id TEXT NOT NULL DEFAULT '', spec_type TEXT NOT NULL DEFAULT 'spec', content TEXT NOT NULL DEFAULT '', status TEXT NOT NULL DEFAULT 'pending', created_at TEXT NOT NULL DEFAULT '', updated_at TEXT NOT NULL DEFAULT '')"
}

///|
/// 语料 / 复验记录(跨后端统一结构)。
pub struct SpecRecord {
  pub id : String
  pub task_id : String
  pub spec_type : String
  pub content : String
  pub status : String
  pub created_at : String
  pub updated_at : String
} derive(Eq, Debug)

///|
/// 便捷构造(仅 id / task_id 必填,其余带默认值)。
pub fn SpecRecord::new(
  id~ : String,
  task_id~ : String,
  spec_type? : String = "spec",
  content? : String = "",
  status? : String = "pending",
  created_at? : String = "",
  updated_at? : String = "",
) -> SpecRecord {
  { id, task_id, spec_type, content, status, created_at, updated_at, }
}

///|
/// 记录转 JSON(供 MCP 工具输出,content 不展开以免撑爆响应)。
pub fn SpecRecord::to_json(self : SpecRecord) -> Json {
  Json::object({
    "id": Json::string(self.id),
    "task_id": Json::string(self.task_id),
    "spec_type": Json::string(self.spec_type),
    "status": Json::string(self.status),
    "created_at": Json::string(self.created_at),
    "updated_at": Json::string(self.updated_at),
  })
}

// —— SQLite 后端 ——

///|
/// 确保 specs 表存在(幂等;旧库自动补齐)。
pub fn SqliteStore::ensure_specs_table(self : SqliteStore) -> Bool {
  match self.db {
    None => false
    Some(db) => db.exec(specs_table_sql())
  }
}

///|
/// 写入 / 覆盖一条语料记录(UPSERT,主键 id)。
pub fn SqliteStore::upsert_spec(
  self : SqliteStore,
  rec : SpecRecord,
) -> Result[Unit, String] {
  match self.db {
    None => Err("sqlite store 未打开")
    Some(db) => {
      ignore(self.ensure_specs_table())
      let sql = "INSERT INTO specs (id, task_id, spec_type, content, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET task_id=excluded.task_id, spec_type=excluded.spec_type, content=excluded.content, status=excluded.status, updated_at=excluded.updated_at"
      match db.prepare(sql) {
        None => Err("sqlite prepare 失败: upsert_spec")
        Some(stmt) => {
          ignore(
            stmt.bind(1, @sqlite.SqlValue::Text(@encoding.encode(UTF8, rec.id))),
          )
          ignore(
            stmt.bind(
              2,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, rec.task_id)),
            ),
          )
          ignore(
            stmt.bind(
              3,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, rec.spec_type)),
            ),
          )
          ignore(
            stmt.bind(
              4,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, rec.content)),
            ),
          )
          ignore(
            stmt.bind(
              5,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, rec.status)),
            ),
          )
          ignore(
            stmt.bind(
              6,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, rec.created_at)),
            ),
          )
          ignore(
            stmt.bind(
              7,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, rec.updated_at)),
            ),
          )
          let exec_ok = stmt.execute()
          stmt.finalize()
          if exec_ok {
            Ok(())
          } else {
            Err("sqlite 写入语料失败: \{rec.id}")
          }
        }
      }
    }
  }
}

///|
/// 按 id 读取单条语料记录。
pub fn SqliteStore::get_spec(self : SqliteStore, id : String) -> SpecRecord? {
  match self.db {
    None => None
    Some(db) => {
      let sql = "SELECT id, task_id, spec_type, content, status, created_at, updated_at FROM specs WHERE id = ?"
      match db.prepare(sql) {
        None => None
        Some(stmt) => {
          ignore(
            stmt.bind(1, @sqlite.SqlValue::Text(@encoding.encode(UTF8, id))),
          )
          let found = if stmt.step() { Some(row_to_spec(stmt)) } else { None }
          stmt.finalize()
          found
        }
      }
    }
  }
}

///|
/// 列出某任务的全部语料 / 复验记录(按 created_at、id 升序)。
pub fn SqliteStore::list_specs_by_task(
  self : SqliteStore,
  task_id : String,
) -> Array[SpecRecord] {
  let out : Array[SpecRecord] = []
  match self.db {
    None => out
    Some(db) => {
      ignore(self.ensure_specs_table())
      let sql = "SELECT id, task_id, spec_type, content, status, created_at, updated_at FROM specs WHERE task_id = ? ORDER BY created_at ASC, id ASC"
      match db.prepare(sql) {
        None => out
        Some(stmt) => {
          ignore(
            stmt.bind(
              1,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, task_id)),
            ),
          )
          while stmt.step() {
            out.push(row_to_spec(stmt))
          }
          stmt.finalize()
          out
        }
      }
    }
  }
}

///|
/// 更新语料状态(可同时更新内容与时间戳)。
pub fn SqliteStore::update_spec_status(
  self : SqliteStore,
  id : String,
  status : String,
  content : String,
  updated_at : String,
) -> Result[Unit, String] {
  match self.db {
    None => Err("sqlite store 未打开")
    Some(db) => {
      let sql = "UPDATE specs SET status = ?, content = ?, updated_at = ? WHERE id = ?"
      match db.prepare(sql) {
        None => Err("sqlite prepare 失败: update_spec_status")
        Some(stmt) => {
          ignore(
            stmt.bind(1, @sqlite.SqlValue::Text(@encoding.encode(UTF8, status))),
          )
          ignore(
            stmt.bind(
              2,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, content)),
            ),
          )
          ignore(
            stmt.bind(
              3,
              @sqlite.SqlValue::Text(@encoding.encode(UTF8, updated_at)),
            ),
          )
          ignore(
            stmt.bind(4, @sqlite.SqlValue::Text(@encoding.encode(UTF8, id))),
          )
          let exec_ok = stmt.execute()
          stmt.finalize()
          if exec_ok {
            Ok(())
          } else {
            Err("sqlite 更新语料失败: \{id}")
          }
        }
      }
    }
  }
}

// —— 行反序列化 ——

///|
/// 结果行 -> SpecRecord(列序与 SELECT 语句一致)。
fn row_to_spec(stmt : @sqlite.Statement) -> SpecRecord {
  {
    id: str_from_bytes(stmt.column_text(0)),
    task_id: str_from_bytes(stmt.column_text(1)),
    spec_type: str_from_bytes(stmt.column_text(2)),
    content: str_from_bytes(stmt.column_text(3)),
    status: str_from_bytes(stmt.column_text(4)),
    created_at: str_from_bytes(stmt.column_text(5)),
    updated_at: str_from_bytes(stmt.column_text(6)),
  }
}