class FeishuApiClient

def commit_version(app_id, version_id)

def commit_version(app_id, version_id)
  post_json("#{FEISHU_API_BASE}/publish/commit/#{app_id}/#{version_id}", {})
end

def create_app(name, desc)

def create_app(name, desc)
  post_json("#{FEISHU_API_BASE}/app/create", {
    appSceneType: 0,
    name:         name,
    desc:         desc,
    avatar:       "",
    i18n: { zh_cn: { name: name, description: desc } },
    primaryLang:  "zh_cn"
  })
end

def create_version(app_id, version: "1.0.0")

def create_version(app_id, version: "1.0.0")
  post_json("#{FEISHU_API_BASE}/app_version/create/#{app_id}", {
    clientId:             app_id,
    appVersion:           version,
    changeLog:            "Initial release",
    autoPublish:          false,
    pcDefaultAbility:     "bot",
    mobileDefaultAbility: "bot"
  })
end

def enable_bot(app_id)

def enable_bot(app_id)
  post_json("#{FEISHU_API_BASE}/robot/switch/#{app_id}", { enable: true })
end

def get_all_scopes(app_id)

def get_all_scopes(app_id)
  get_json("#{FEISHU_API_BASE}/scope/all/#{app_id}")
end

def get_app_info(app_id)

def get_app_info(app_id)
  get_json("#{FEISHU_API_BASE}/app/#{app_id}")
end

def get_event(app_id)

def get_event(app_id)
  get_json("#{FEISHU_API_BASE}/event/#{app_id}")
end

def get_json(url)

Uses window.csrfToken — required by all /developers/v1/ endpoints.
Execute a GET fetch in the browser page context.
def get_json(url)
  js = <<~JS
    (async () => {
      const csrfToken = window.csrfToken || '';
      const resp = await fetch(#{url.to_json}, {
        method: 'GET',
        credentials: 'include',
        headers: {
          'accept': '*/*',
          'x-timezone-offset': '-480',
          'x-csrf-token': csrfToken
        }
      });
      return await resp.text();
    })()
  JS
  run_fetch(js, url)
end

def get_secret(app_id)

def get_secret(app_id)
  get_json("#{FEISHU_API_BASE}/secret/#{app_id}")
end

def initialize(browser_session)

def initialize(browser_session)
  @browser = browser_session
end

def post_json(url, payload)

Uses window.csrfToken (set by Feishu's own JS) — the correct token for /developers/v1/ APIs.
Execute a POST fetch in the browser page context.
def post_json(url, payload)
  js = <<~JS
    (async () => {
      const csrfToken = window.csrfToken || '';
      const resp = await fetch(#{url.to_json}, {
        method: 'POST',
        credentials: 'include',
        headers: {
          'accept': '*/*',
          'content-type': 'application/json',
          'origin': 'https://open.feishu.cn',
          'referer': 'https://open.feishu.cn/app',
          'x-timezone-offset': '-480',
          'x-csrf-token': csrfToken
        },
        body: #{JSON.generate(payload).to_json}
      });
      return await resp.text();
    })()
  JS
  run_fetch(js, url)
end

def release_version(app_id, version_id)

def release_version(app_id, version_id)
  post_json("#{FEISHU_API_BASE}/publish/release/#{app_id}/#{version_id}", {
    clientId:  app_id,
    versionId: version_id
  })
end

def run_fetch(js, url)

def run_fetch(js, url)
  raw = @browser.evaluate(js)
  # The MCP tool may wrap result in markdown code blocks
  json_text = @browser.send(:extract_string_value, raw)
  JSON.parse(json_text)
rescue JSON::ParserError => e
  raise "JSON parse error from #{url}: #{e.message} — raw: #{raw.to_s[0..300]}"
end

def switch_callback_mode(app_id, mode: 4)

def switch_callback_mode(app_id, mode: 4)
  post_json("#{FEISHU_API_BASE}/callback/switch/#{app_id}", { callbackMode: mode })
end

def switch_event_mode(app_id, mode: 4)

def switch_event_mode(app_id, mode: 4)
  post_json("#{FEISHU_API_BASE}/event/switch/#{app_id}", { eventMode: mode })
end

def update_event(app_id, event_mode:)

def update_event(app_id, event_mode:)
  post_json("#{FEISHU_API_BASE}/event/update/#{app_id}", {
    operation:  "add",
    events:     ["im.message.receive_v1"],
    eventMode:  event_mode
  })
end

def update_scopes(app_id, scope_ids)

def update_scopes(app_id, scope_ids)
  post_json("#{FEISHU_API_BASE}/scope/update/#{app_id}", {
    clientId:    app_id,
    appScopeIDs: scope_ids,
    userScopeIDs: [],
    scopeIds:    [],
    operation:   "add"
  })
end