class Clacky::Channel::Adapters::Wecom::Adapter

Receives messages via WebSocket long connection and sends via bot API.
WeCom (Enterprise WeChat) adapter.

def self.env_keys

def self.env_keys
  %w[IM_WECOM_BOT_ID IM_WECOM_SECRET]
end

def self.platform_config(data)

def self.platform_config(data)
  {
    bot_id: data["IM_WECOM_BOT_ID"],
    secret: data["IM_WECOM_SECRET"]
  }
end

def self.platform_id

def self.platform_id
  :wecom
end

def self.set_env_data(data, config)

def self.set_env_data(data, config)
  data["IM_WECOM_BOT_ID"] = config[:bot_id]
  data["IM_WECOM_SECRET"] = config[:secret]
end

def handle_raw_message(raw)

def handle_raw_message(raw)
  msgtype = raw["msgtype"]
  return unless %w[text image file].include?(msgtype)
  chat_id = raw["chatid"] || raw.dig("from", "userid")
  return unless chat_id
  user_id = raw.dig("from", "userid")
  chat_type = raw["chattype"] == "group" ? :group : :direct
  text  = ""
  files = []
  case msgtype
  when "text"
    text = raw.dig("text", "content").to_s.strip
    return if text.empty?
  when "image"
    url    = raw.dig("image", "url")
    aeskey = raw.dig("image", "aeskey")
    return unless url
    result = MediaDownloader.download(url, aeskey)
    mime = MediaDownloader.detect_mime(result[:body])
    if result[:body].bytesize > MAX_IMAGE_BYTES
      @ws_client.send_message(chat_id, "Image too large (#{(result[:body].bytesize / 1024.0).round(0).to_i}KB), max #{MAX_IMAGE_BYTES / 1024}KB")
      return
    end
    require "base64"
    data_url = "data:#{mime};base64,#{Base64.strict_encode64(result[:body])}"
    files = [{ name: "image.jpg", mime_type: mime, data_url: data_url }]
  when "file"
    url      = raw.dig("file", "url")
    aeskey   = raw.dig("file", "aeskey")
    return unless url
    filename = raw.dig("file", "name") || raw.dig("file", "filename") || "attachment"
    result   = MediaDownloader.download(url, aeskey)
    filename = result[:filename] || filename
    saved = Clacky::Utils::FileProcessor.save(body: result[:body], filename: filename)
    files = [saved]
  end
  event = {
    type: :message,
    platform: :wecom,
    chat_id: chat_id,
    user_id: user_id,
    text: text,
    files: files,
    message_id: raw["msgid"],
    timestamp: raw["create_time"] ? Time.at(raw["create_time"]) : Time.now,
    chat_type: chat_type,
    raw: raw
  }
  @on_message&.call(event)
rescue => e
  Clacky::Logger.error("[WecomAdapter] handle_raw_message error: #{e.message}\n#{e.backtrace.first(3).join("\n")}")
  begin
    @ws_client.send_message(chat_id, "Error processing message: #{e.message}") if chat_id
  rescue
    nil
  end
end

def initialize(config)

def initialize(config)
  @config = config
  @ws_client = WSClient.new(
    bot_id: config[:bot_id],
    secret: config[:secret],
    ws_url: config[:ws_url] || WSClient::WS_URL
  )
  @running = false
  @on_message = nil
end

def send_file(chat_id, path, name: nil)

def send_file(chat_id, path, name: nil)
  @ws_client.send_file(chat_id, path, name: name)
end

def send_text(chat_id, text, reply_to: nil)

def send_text(chat_id, text, reply_to: nil)
  @ws_client.send_message(chat_id, text)
end

def start(&on_message)

def start(&on_message)
  @running = true
  @on_message = on_message
  @ws_client.start do |raw|
    handle_raw_message(raw)
  end
rescue WSClient::AuthError => e
  Clacky::Logger.error("[WecomAdapter] Authentication failed, not retrying: #{e.message}")
end

def stop

def stop
  @running = false
  @ws_client.stop
end

def validate_config(config)

def validate_config(config)
  errors = []
  errors << "bot_id is required" if config[:bot_id].nil? || config[:bot_id].empty?
  errors << "secret is required" if config[:secret].nil? || config[:secret].empty?
  errors
end