// Tests for web -> local outbound draft pull. Run: node --experimental-strip-types --test
import { test } from "node:test";
import assert from "node:assert/strict";
import { DatabaseSync } from "node:sqlite";
import {
  markOutboundDraftAcked,
  pendingOutboundDraftAcks,
  storeOutboundDrafts,
  type WebOutboundDraft,
} from "./outboundDrafts.ts";

function freshDb(): DatabaseSync {
  const db = new DatabaseSync(":memory:");
  db.exec("PRAGMA foreign_keys=ON;");
  db.exec(`CREATE TABLE unified_conversation (
    id TEXT PRIMARY KEY, workspace_id TEXT NOT NULL, channel TEXT NOT NULL, account_id TEXT,
    external_id TEXT, title TEXT, contact_id TEXT, last_ts INTEGER, unread INTEGER NOT NULL DEFAULT 0,
    archived_at INTEGER, muted INTEGER NOT NULL DEFAULT 0, updated_at INTEGER NOT NULL, deleted_at INTEGER);`);
  return db;
}

const draft = (body = "Reply from web"): WebOutboundDraft => ({
  id: "66666666-6666-4666-8666-666666666666",
  conversationId: "77777777-7777-4777-8777-777777777777",
  providerConversationId: "wa-chat-local",
  channel: "WHATSAPP",
  accountId: "acc-local",
  externalId: "wa-chat-local",
  title: "Local Client",
  body,
  status: "pending",
  source: "web",
  executionTarget: "local-device",
  requiresOnlineDevice: true,
  createdAt: 1000,
  updatedAt: 1100,
});

test("storeOutboundDrafts attaches web draft to existing native WhatsApp conversation", () => {
  const db = freshDb();
  db.prepare(
    `INSERT INTO unified_conversation
       (id, workspace_id, channel, account_id, external_id, title, last_ts, unread, updated_at)
     VALUES ('wa:acc-local:wa-chat-local', 'local', 'WHATSAPP', 'acc-local', 'wa-chat-local', 'Local Client', 900, 0, 900)`,
  ).run();

  assert.deepEqual(storeOutboundDrafts(db, [draft()]), { drafts: 1, stored: 1 });

  const row = db.prepare("SELECT * FROM outbound_draft WHERE id=?").get(draft().id) as any;
  assert.equal(row.conversation_id, "wa:acc-local:wa-chat-local");
  assert.equal(row.account_id, "acc-local");
  assert.equal(row.external_id, "wa-chat-local");
  assert.equal(row.body, "Reply from web");
  assert.equal(row.status, "pending");
  assert.equal(row.source, "web");
  assert.equal(row.web_message_id, draft().id);
});

test("storeOutboundDrafts is idempotent and does not revert locally completed drafts", () => {
  const db = freshDb();
  storeOutboundDrafts(db, [draft()]);
  db.prepare("UPDATE outbound_draft SET status='sent', body='Approved local copy' WHERE id=?").run(draft().id);
  db.prepare("UPDATE outbound_draft SET provider_msg_id='wa-provider-1' WHERE id=?").run(draft().id);

  assert.deepEqual(storeOutboundDrafts(db, [draft("Changed on web")]), { drafts: 1, stored: 1 });

  const row = db.prepare("SELECT status, body FROM outbound_draft WHERE id=?").get(draft().id) as any;
  assert.equal(row.status, "sent");
  assert.equal(row.body, "Approved local copy");

  const pending = pendingOutboundDraftAcks(db);
  assert.deepEqual(pending, [{
    id: draft().id,
    webMessageId: draft().id,
    status: "sent",
    providerMsgId: "wa-provider-1",
    error: null,
  }]);

  markOutboundDraftAcked(db, draft().id, "sent", 2000);
  assert.deepEqual(pendingOutboundDraftAcks(db), []);
});

test("pendingOutboundDraftAcks includes browser placed status", () => {
  const db = freshDb();
  storeOutboundDrafts(db, [{ ...draft(), channel: "LINKEDIN", accountId: "li1", externalId: "thread-1" }]);
  db.prepare("UPDATE outbound_draft SET status='placed', provider_msg_id='li:placed:thread-1' WHERE id=?").run(draft().id);

  assert.deepEqual(pendingOutboundDraftAcks(db), [{
    id: draft().id,
    webMessageId: draft().id,
    status: "placed",
    providerMsgId: "li:placed:thread-1",
    error: null,
  }]);
});
