import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";

import {
  NEW_CHAT_DRAFT_ID,
  chatDraftStorageKey,
  clearChatDraft,
  readChatDraft,
  writeChatDraft,
} from "../web/static/js/chat_drafts.js";

class MemoryStorage {
  constructor() { this.values = new Map(); }
  getItem(key) { return this.values.get(key) ?? null; }
  setItem(key, value) { this.values.set(key, String(value)); }
  removeItem(key) { this.values.delete(key); }
}

test("chat drafts are isolated by user and conversation", () => {
  const storage = new MemoryStorage();
  writeChatDraft(storage, "user-a", "task-1", "任务一草稿", 1);
  writeChatDraft(storage, "user-a", "task-2", "任务二草稿", 2);
  writeChatDraft(storage, "user-b", "task-1", "另一用户草稿", 3);

  assert.equal(readChatDraft(storage, "user-a", "task-1"), "任务一草稿");
  assert.equal(readChatDraft(storage, "user-a", "task-2"), "任务二草稿");
  assert.equal(readChatDraft(storage, "user-b", "task-1"), "另一用户草稿");
  assert.notEqual(chatDraftStorageKey("user-a"), chatDraftStorageKey("user-b"));
});

test("new conversation draft persists and blank content clears it", () => {
  const storage = new MemoryStorage();
  writeChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID, "未创建对话", 1);
  assert.equal(readChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID), "未创建对话");

  clearChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID);
  assert.equal(readChatDraft(storage, "user-a", NEW_CHAT_DRAFT_ID), "");
  assert.equal(storage.getItem(chatDraftStorageKey("user-a")), null);
});

test("chat integrates draft save, restore, migration, and sent cleanup", () => {
  const source = readFileSync(new URL("../web/static/js/chat.js", import.meta.url), "utf8");
  assert.match(source, /export async function selectTask\(tid\) \{\s*persistComposerDraft\(\)/);
  assert.match(source, /state\.taskId = tid;\s*restoreComposerDraft\(tid\)/);
  assert.match(source, /persistComposerDraft\(t\.task_id\)/);
  assert.match(source, /clearChatDraft\(localStorage, state\.userId, taskId\)/);
  assert.match(source, /addEventListener\("input", \(\) => \{\s*scheduleComposerDraftSave\(\)/);
  assert.match(source, /addEventListener\("pagehide", \(\) => persistComposerDraft\(\)\)/);
});
