import assert from "node:assert/strict";
import test from "node:test";
import {
  clearFeishuAccessTokenCacheForTests,
  readFeishuSource,
} from "../lib/feishu-client.ts";

const bindings = {
  FEISHU_APP_ID: "cli_test",
  FEISHU_APP_SECRET: "secret_test",
};

function apiResponse(data) {
  return Response.json({ code: 0, msg: "success", data });
}

function fakeFeishu(options = {}) {
  const calls = [];
  const fetchImpl = async (input, init = {}) => {
    const url = new URL(String(input));
    calls.push({ url, init });
    if (url.pathname.endsWith("/tenant_access_token/internal")) {
      return Response.json({
        code: 0,
        msg: "success",
        tenant_access_token: "tenant-test",
        expire: 7200,
      });
    }
    if (url.pathname.endsWith("/wiki/v2/spaces/get_node")) {
      return apiResponse({
        node: {
          obj_type: "sheet",
          obj_token: "spreadsheet-test",
        },
      });
    }
    if (url.pathname.endsWith("/sheets/query")) {
      return apiResponse({
        sheets:
          options.sheets ??
          [
            {
              sheet_id: "sheet-one",
              title: "内容池",
              resource_type: "sheet",
              hidden: false,
              grid_properties: { row_count: 20, column_count: 10 },
            },
          ],
      });
    }
    if (url.pathname.endsWith("/values_batch_get")) {
      return apiResponse({
        valueRanges: [
          {
            values: [
              ["作品ID", "标题", "标签", "正文", null, null],
              [
                7,
                "一篇测试笔记",
                "#测试 #KOC",
                "测试正文",
                {
                  type: "embed-image",
                  fileToken: "file-token-one",
                  width: 1080,
                  height: 1440,
                },
                [
                  {
                    type: "embed-image",
                    fileToken: "file-token-two",
                    width: 1080,
                    height: 1440,
                  },
                ],
              ],
              [8, "", "", "空标题不会导入"],
            ],
          },
        ],
      });
    }
    throw new Error(`Unexpected request: ${url.pathname}`);
  };
  return { calls, fetchImpl };
}

test("resolves a wiki sheet and imports title, body, tags, and all images", async () => {
  clearFeishuAccessTokenCacheForTests();
  const { calls, fetchImpl } = fakeFeishu();
  const source = await readFeishuSource(
    "https://tenant.feishu.cn/wiki/wiki-test",
    bindings,
    fetchImpl,
  );

  assert.equal(source.spreadsheetToken, "spreadsheet-test");
  assert.equal(source.sheetId, "sheet-one");
  assert.equal(source.sheetName, "内容池");
  assert.equal(source.rows.length, 1);
  assert.equal(source.rows[0].sourceRow, 7);
  assert.equal(source.rows[0].body, "测试正文\n\n#测试 #KOC");
  assert.deepEqual(
    source.rows[0].images.map((image) => image.fileToken),
    ["file-token-one", "file-token-two"],
  );
  assert.deepEqual(source.columns, [
    "作品ID",
    "标题",
    "标签",
    "正文",
    "图片1",
    "图片2",
  ]);
  const valuesCall = calls.find((call) =>
    call.url.pathname.endsWith("/values_batch_get"),
  );
  assert.equal(valuesCall.url.searchParams.get("ranges"), "sheet-one!A1:J20");
});

test("imports video attachments from a Feishu video task sheet", async () => {
  clearFeishuAccessTokenCacheForTests();
  const { fetchImpl } = fakeFeishu();
  const videoFetch = async (input, init = {}) => {
    const url = new URL(String(input));
    if (url.pathname.endsWith("/values_batch_get")) {
      return apiResponse({
        valueRanges: [
          {
            values: [
              ["标题", "内容（标题+正文+tag）", "视频"],
              [
                "一条测试视频",
                "一条测试视频\n视频正文 #测试",
                {
                  type: "attachment",
                  fileToken: "video-token-one",
                  text: "demo.mp4",
                  mimeType: "video/mp4",
                  size: 1024,
                },
              ],
            ],
          },
        ],
      });
    }
    return fetchImpl(input, init);
  };
  const source = await readFeishuSource(
    "https://tenant.feishu.cn/wiki/wiki-test",
    bindings,
    videoFetch,
  );

  assert.equal(source.rows.length, 1);
  assert.equal(source.rows[0].title, "一条测试视频");
  assert.equal(source.rows[0].body, "一条测试视频\n视频正文 #测试");
  assert.deepEqual(source.rows[0].videos, [
    {
      index: 1,
      fileToken: "video-token-one",
      name: "demo.mp4",
      mimeType: "video/mp4",
      size: 1024,
    },
  ]);
});

test("requires an exact sheet link when a workbook has multiple visible sheets", async () => {
  clearFeishuAccessTokenCacheForTests();
  const { fetchImpl } = fakeFeishu({
    sheets: [
      {
        sheet_id: "one",
        title: "内容A",
        resource_type: "sheet",
        hidden: false,
      },
      {
        sheet_id: "two",
        title: "内容B",
        resource_type: "sheet",
        hidden: false,
      },
    ],
  });

  await assert.rejects(
    readFeishuSource(
      "https://tenant.feishu.cn/wiki/wiki-test",
      bindings,
      fetchImpl,
    ),
    /包含多个工作表/,
  );
});

test("rejects a wiki node that is not a spreadsheet", async () => {
  clearFeishuAccessTokenCacheForTests();
  const fetchImpl = async (input) => {
    const url = new URL(String(input));
    if (url.pathname.endsWith("/tenant_access_token/internal")) {
      return Response.json({
        code: 0,
        msg: "success",
        tenant_access_token: "tenant-test",
        expire: 7200,
      });
    }
    return apiResponse({
      node: { obj_type: "docx", obj_token: "document-test" },
    });
  };

  await assert.rejects(
    readFeishuSource(
      "https://tenant.feishu.cn/wiki/wiki-test",
      bindings,
      fetchImpl,
    ),
    /不是电子表格/,
  );
});
