// 可注时钟(方案 §3.4.1 / D-M0-3):core 默认走 @env.now(),测试注入固定钟。
// MoonBit 单线程事件循环,全局 Ref 安全(无并发竞争)。

///|
let clock_ref : Ref[((() -> String))?] = Ref::new(None)

///|
pub fn set_clock(f : (() -> String)?) -> Unit {
  clock_ref.val = f
}

///|
/// 当前墙钟毫秒(@env.now() 的单位实测为 epoch 毫秒,见 model_test)
pub fn epoch_millis() -> Int64 {
  @env.now().to_int64()
}

///|
/// 当前墙钟秒
pub fn epoch_secs() -> Int64 {
  epoch_millis() / 1000L
}

///|
pub fn current_time_str() -> String {
  match clock_ref.val {
    Some(f) => f()
    None => format_unix_utc(epoch_secs())
  }
}

///|
/// Format unix seconds (UTC) as `yyyy-MM-dd HH:mm:ss`(civil_from_days, Howard Hinnant)
pub fn format_unix_utc(secs : Int64) -> String {
  let z = secs / 86400L + 719468L
  let era = (if z >= 0L { z } else { z - 146096L }) / 146097L
  let doe = (z - era * 146097L).to_int()
  let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365
  let y = yoe + (era * 400L).to_int()
  let doy = doe - (365 * yoe + yoe / 4 - yoe / 100)
  let mp = (5 * doy + 2) / 153
  let d = doy - (153 * mp + 2) / 5 + 1
  let m = if mp < 10 { mp + 3 } else { mp - 9 }
  let y = if m <= 2 { y + 1 } else { y }
  let tod = (secs % 86400L).to_int()
  let hh = tod / 3600
  let mm = (tod % 3600) / 60
  let ss = tod % 60
  let pad = (n : Int, w : Int) => {
    let s = n.to_string()
    let b = StringBuilder::new()
    for _ in 0..<(w - s.length()) {
      b.write_char('0')
    }
    b.write_string(s)
    b.to_string()
  }

  "\{pad(y, 4)}-\{pad(m, 2)}-\{pad(d, 2)} \{pad(hh, 2)}:\{pad(mm, 2)}:\{pad(ss, 2)}"
}