const test = require("node:test");
const assert = require("node:assert/strict");

const {
  bridgeEventFromFeishu,
  bridgeEventFromNormalizedMessage,
  buildChannelOptions,
  ignoreReason,
  parsePolicyEnv,
} = require("../../external_connector/node/feishu_event_utils");

test("ignores Feishu app or bot sender events", () => {
  assert.equal(ignoreReason({ sender: { sender_type: "app" }, message: { content: "{\"text\":\"hello\"}" } }), "sender_type:app");
  assert.equal(ignoreReason({ sender: { sender_type: "bot" }, message: { content: "{\"text\":\"hello\"}" } }), "sender_type:bot");
});

test("ignores Feishu slash commands intended for the platform integration", () => {
  assert.equal(ignoreReason({ sender: { sender_type: "user" }, message: { content: "{\"text\":\"/feishu start\"}" } }), "feishu_command");
});

test("keeps user messages and records sender type metadata", () => {
  const event = bridgeEventFromFeishu(
    {
      event_id: "evt_1",
      sender: { sender_type: "user", sender_id: { open_id: "ou_user" } },
      message: {
        message_id: "om_1",
        chat_id: "oc_1",
        chat_type: "p2p",
        message_type: "text",
        content: "{\"text\":\"hello\"}",
      },
    },
    { connectionId: "conn_1", channelId: "feishu-main", accountId: "feishu:cli_1" },
  );

  assert.equal(ignoreReason({ sender: { sender_type: "user" }, message: { content: "{\"text\":\"hello\"}" } }), "");
  assert.equal(event.content, "hello");
  assert.equal(event.peerId, "ou_user");
  assert.equal(event.metadata.senderType, "user");
});

test("uses chat id as peer id for group messages", () => {
  const event = bridgeEventFromFeishu(
    {
      event_id: "evt_1",
      sender: { sender_type: "user", sender_id: { open_id: "ou_user" } },
      message: {
        message_id: "om_1",
        chat_id: "oc_group",
        chat_type: "group",
        message_type: "text",
        content: "{\"text\":\"@bot hello\"}",
      },
    },
    { connectionId: "conn_1", channelId: "feishu-main", accountId: "feishu:cli_1" },
  );

  assert.equal(event.peerType, "group");
  assert.equal(event.peerId, "oc_group");
  assert.equal(event.userId, "ou_user");
});

test("builds SDK channel options from explicit Feishu policy environment", () => {
  const policy = parsePolicyEnv({
    FEISHU_REQUIRE_MENTION_IN_GROUPS: "false",
    FEISHU_RESPOND_TO_MENTION_ALL: "true",
    FEISHU_DM_MODE: "allowlist",
    FEISHU_ALLOW_FROM: "ou_1, ou_2",
    FEISHU_GROUP_ALLOW_FROM: "oc_1\noc_2",
    FEISHU_MAX_MESSAGE_CHARS: "1234",
    FEISHU_TEXT_BATCH_DELAY_MS: "250",
    FEISHU_TEXT_BATCH_MAX_MESSAGES: "5",
    FEISHU_TEXT_BATCH_MAX_CHARS: "2048",
  });
  const options = buildChannelOptions({
    appId: "cli_1",
    appSecret: "secret",
    domain: "feishu",
    policy,
  });

  assert.equal(options.policy.requireMention, false);
  assert.equal(options.policy.respondToMentionAll, true);
  assert.equal(options.policy.dmMode, "allowlist");
  assert.deepEqual(options.policy.dmAllowlist, ["ou_1", "ou_2"]);
  assert.deepEqual(options.policy.groupAllowlist, ["oc_1", "oc_2"]);
  assert.equal(options.outbound.textChunkLimit, 1234);
  assert.equal(options.safety.batch.text.delayMs, 250);
  assert.equal(options.safety.batch.text.maxMessages, 5);
  assert.equal(options.safety.batch.text.maxChars, 2048);
  assert.equal(options.includeRawEvent, true);
});

test("normalizes SDK message events for Beaver bridge", () => {
  const event = bridgeEventFromNormalizedMessage(
    {
      messageId: "om_1",
      chatId: "oc_group",
      chatType: "group",
      senderId: "ou_user",
      content: "hello",
      rawContentType: "text",
      resources: [{ type: "image", fileKey: "img_1", fileName: "photo.png" }],
      mentions: [{ openId: "ou_bot", name: "Beaver", isBot: true }],
      mentionAll: false,
      mentionedBot: true,
      createTime: 1710000000000,
      raw: { event_id: "evt_1" },
    },
    { connectionId: "conn_1", channelId: "feishu-main", accountId: "feishu:cli_1" },
    { maxMessageChars: 100 },
  );

  assert.equal(event.eventId, "evt_1");
  assert.equal(event.peerType, "group");
  assert.equal(event.peerId, "oc_group");
  assert.equal(event.userId, "ou_user");
  assert.equal(event.threadId, "oc_group");
  assert.match(event.content, /^hello/);
  assert.deepEqual(event.metadata.mentions[0].openId, "ou_bot");
  assert.deepEqual(event.metadata.resources[0].type, "image");
});

test("uses sender id as peer id for SDK direct messages", () => {
  const event = bridgeEventFromNormalizedMessage(
    {
      messageId: "om_dm",
      chatId: "oc_dm",
      chatType: "p2p",
      senderId: "ou_user",
      content: "hello dm",
      rawContentType: "text",
      resources: [],
      mentions: [],
      mentionAll: false,
      mentionedBot: false,
      createTime: 1710000000000,
      raw: { header: { event_id: "evt_dm" } },
    },
    { connectionId: "conn_1", channelId: "feishu-main", accountId: "feishu:cli_1" },
  );

  assert.equal(event.peerType, "dm");
  assert.equal(event.peerId, "ou_user");
  assert.equal(event.threadId, "oc_dm");
});

test("drops empty and oversized SDK message events", () => {
  assert.equal(
    bridgeEventFromNormalizedMessage(
      {
        messageId: "om_empty",
        chatId: "oc_dm",
        chatType: "p2p",
        senderId: "ou_user",
        content: "   ",
        rawContentType: "text",
        resources: [],
        mentions: [],
        mentionAll: false,
        mentionedBot: false,
        createTime: 1710000000000,
      },
      { connectionId: "conn_1", channelId: "feishu-main", accountId: "feishu:cli_1" },
    ),
    null,
  );
  assert.equal(
    bridgeEventFromNormalizedMessage(
      {
        messageId: "om_big",
        chatId: "oc_dm",
        chatType: "p2p",
        senderId: "ou_user",
        content: "x".repeat(11),
        rawContentType: "text",
        resources: [],
        mentions: [],
        mentionAll: false,
        mentionedBot: false,
        createTime: 1710000000000,
      },
      { connectionId: "conn_1", channelId: "feishu-main", accountId: "feishu:cli_1" },
      { maxMessageChars: 10 },
    ),
    null,
  );
});
