///|
/// JS 目标 HTTP 服务派发层(examples/js-server 构建产物)。
/// Node 宿主通过构建脚本(tools/build-js-server.js)提取本包的
/// js_captcha_* 函数并挂到 module.exports,HTTP 路由只做 JSON ↔ 调用。

///|
/// 全局服务状态:进程内单例(内存缓存 + 内存频控),与 Node 单线程模型一致。
/// 分布式部署时应替换为共享缓存实现(实现 Cache trait,如 Redis)。
priv struct GlobalState {
  mut service : @service.CaptchaService?
  cache : @cache.MemoryCache
}

///|
/// 合成底图:渐变背景(示例免资源文件,开箱即用;
/// 生产请用 tools/gen-assets.js 嵌入真实底图)。
fn gradient_bg(w : Int, h : Int, seed : Int) -> @image.PngImage {
  let rgba : FixedArray[Int] = FixedArray::make(w * h * 4, 0)
  for y in 0.. @image.PngImage {
  let w = 94
  let h = 310
  let rgba : FixedArray[Int] = FixedArray::make(w * h * 4, 0)
  for y in y0..= y1 - 3 || x < x0 + 3 || x >= x1 - 3 {
        100
      } else {
        255
      }
    }
  }
  { width: w, height: h, rgba, }
}

///|
fn build_pool() -> @image.ImagePool {
  let pool = @image.ImagePool::new()
  pool.add_original(gradient_bg(310, 155, 1))
  pool.add_original(gradient_bg(310, 155, 2))
  pool.add_slider(rect_slider(24, 20, 70, 80))
  pool.add_slider(rect_slider(14, 30, 80, 100))
  pool.add_click(gradient_bg(310, 155, 3))
  pool
}

///|
let global_state : GlobalState = {
  service: None,
  cache: @cache.MemoryCache::new(fn() { @env.now().reinterpret_as_int64() }),
}

///|

///|
fn state() -> GlobalState {
  global_state
}

///|
fn ensure_service(font_bytes : FixedArray[Int]?) -> Result[Unit, String] {
  let st = state()
  match st.service {
    Some(_) =>
      // 已初始化;仅当携带字体且当前无字体时热更新
      match font_bytes {
        Some(bytes) =>
          match @image.Font::parse(bytes) {
            Ok(f) => {
              match st.service {
                Some(s) => s.set_font(Some(f))
                None => ()
              }
              Ok(())
            }
            Err(e) => Err(e)
          }
        None => Ok(())
      }
    None => {
      let font : @image.Font? = match font_bytes {
        Some(bytes) =>
          match @image.Font::parse(bytes) {
            Ok(f) => Some(f)
            Err(e) => return Err(e)
          }
        None => None
      }
      st.service = Some(
        @service.CaptchaService::new(
          build_pool(),
          font~,
          limits=@service.RateLimitConfig::default(),
        ),
      )
      Ok(())
    }
  }
}

///|
/// 统一成功应答(repData 为已序列化 JSON 片段)。
fn ok_data(data : String) -> String {
  @protocol.ResponseModel::success_data(data).to_json()
}

///|
/// 请求字段读取。
fn req_str(req : @common.Value, key : String) -> String {
  req.field_str(key).unwrap_or("")
}

///|
/// 初始化(可选字体,Base64 编码的 TTF 字节)。
/// 由宿主在启动时调用一次;重复调用仅热更新字体。
pub fn js_captcha_init(font_b64 : String) -> String {
  let font_bytes : FixedArray[Int]? = if font_b64.length() == 0 {
    None
  } else {
    match @common.base64_decode(font_b64) {
      Some(b) => Some(b)
      None => return "ERR base64 decode failed"
    }
  }
  match ensure_service(font_bytes) {
    Ok(_) => "OK"
    Err(e) => "ERR " + e
  }
}

///|
/// GET /captcha/get。请求 JSON:{"kind":"blockPuzzle","clientId":""}
pub fn js_captcha_get(request : String) -> String {
  let req = match @common.parse_json(request) {
    Ok(v) => v
    Err(e) => return "ERR json: " + e
  }
  let kind = match @service.CaptchaKind::parse(req_str(req, "kind")) {
    Some(k) => k
    None => return "ERR unknown kind"
  }
  match state().service {
    None => "ERR service not initialized"
    Some(svc) =>
      match svc.get(state().cache, kind, client_id=req_str(req, "clientId")) {
        Ok(resp) => ok_data(resp.to_json())
        Err(e) => e.to_response().to_json()
      }
  }
}

///|
/// POST /captcha/check。请求 JSON:
/// {"kind":"blockPuzzle","clientId":"","token":"","pointJson":""}
pub fn js_captcha_check(request : String) -> String {
  let req = match @common.parse_json(request) {
    Ok(v) => v
    Err(e) => return "ERR json: " + e
  }
  let kind = match @service.CaptchaKind::parse(req_str(req, "kind")) {
    Some(k) => k
    None => return "ERR unknown kind"
  }
  match state().service {
    None => "ERR service not initialized"
    Some(svc) =>
      svc
      .check(
        state().cache,
        kind,
        client_id=req_str(req, "clientId"),
        token=req_str(req, "token"),
        point_json=req_str(req, "pointJson"),
      )
      .to_json()
  }
}

///|
/// POST /captcha/verify。请求 JSON:
/// {"clientId":"","captchaVerification":""}
pub fn js_captcha_verify(request : String) -> String {
  let req = match @common.parse_json(request) {
    Ok(v) => v
    Err(e) => return "ERR json: " + e
  }
  match state().service {
    None => "ERR service not initialized"
    Some(svc) =>
      svc
      .verify(
        state().cache,
        client_id=req_str(req, "clientId"),
        captcha_verification=req_str(req, "captchaVerification"),
      )
      .to_json()
  }
}

///|
fn main {
  // 预热:初始化全局服务,并实际调用各派发函数(带副作用,避免 JS 链接器
  // tree-shake 未从 main 可达的入口);宿主构建脚本按 mangling 名提取挂载
  println("mooncaptcha js-server payload: init=" + js_captcha_init(""))
  let _warm_get = js_captcha_get("{\"kind\":\"blockPuzzle\"}")
  let _warm_check = js_captcha_check("{}")
  let _warm_verify = js_captcha_verify("{}")
  let _ = (_warm_get, _warm_check, _warm_verify)
  println("mooncaptcha js-server payload ready")
}