import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { getSlackThread, saveSlackThread } from "@/slack/message-store.js";

describe("slack/message-store", () => {
  let tmp: string;
  let originalCwd: string;

  beforeEach(() => {
    originalCwd = process.cwd();
    tmp = join(tmpdir(), `slack-store-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
    mkdirSync(tmp, { recursive: true });
    process.chdir(tmp);
  });

  afterEach(() => {
    process.chdir(originalCwd);
    rmSync(tmp, { recursive: true, force: true });
  });

  test("save + get round-trip", () => {
    const thread = { channelId: "C123", threadTs: "1234.5678" };
    saveSlackThread("key-1", thread);

    const loaded = getSlackThread("key-1");
    expect(loaded).toEqual(thread);
  });

  test("get returns null for missing key", () => {
    expect(getSlackThread("nonexistent")).toBeNull();
  });

  test("overwrite: second save wins", () => {
    saveSlackThread("overwrite-key", { channelId: "C100", threadTs: "1000.0" });
    saveSlackThread("overwrite-key", { channelId: "C200", threadTs: "2000.0" });

    const loaded = getSlackThread("overwrite-key");
    expect(loaded).toEqual({ channelId: "C200", threadTs: "2000.0" });
  });

  test("file is stored under slack-threads/<key>.json", () => {
    saveSlackThread("my-thread", { channelId: "C999", threadTs: "9999.0" });

    const filePath = join(tmp, "slack-threads", "my-thread.json");
    const content = JSON.parse(readFileSync(filePath, "utf-8")) as {
      channelId: string;
      threadTs: string;
    };
    expect(content.channelId).toBe("C999");
    expect(content.threadTs).toBe("9999.0");
  });

  test("corrupt JSON file returns null", () => {
    const storeDir = join(tmp, "slack-threads");
    mkdirSync(storeDir, { recursive: true });
    writeFileSync(join(storeDir, "bad.json"), "NOT JSON{{");

    expect(getSlackThread("bad")).toBeNull();
  });

  test("JSON missing required fields returns null", () => {
    const storeDir = join(tmp, "slack-threads");
    mkdirSync(storeDir, { recursive: true });
    writeFileSync(join(storeDir, "partial.json"), JSON.stringify({ channelId: "C1" }));

    expect(getSlackThread("partial")).toBeNull();
  });
});
