import { test } from "node:test";
import assert from "node:assert/strict";
import type { WAMessage, proto } from "@whiskeysockets/baileys";
import { mediaType, parseMessageForDb, unwrapMessage } from "./whatsapp.ts";

const CHAT_JID = "1234567890@s.whatsapp.net";

function messageWith(message: proto.IMessage, id: string): WAMessage {
  return {
    key: { id, remoteJid: CHAT_JID, fromMe: false },
    message,
    messageTimestamp: 1710000000,
  } as WAMessage;
}

function assertStoredMedia(msg: WAMessage, expectedType: string, expectedContent: string): void {
  assert.equal(mediaType(msg), expectedType);
  const parsed = parseMessageForDb(msg);
  assert.notEqual(parsed, null);
  assert.equal(parsed?.id, msg.key.id);
  assert.equal(parsed?.chat_jid, CHAT_JID);
  assert.equal(parsed?.is_from_me, false);
  assert.equal(parsed?.content, expectedContent);
}

test("plain documentMessage is classified and stored from its filename", () => {
  const inner: proto.IMessage = {
    documentMessage: {
      fileName: "deck.pptx",
      mimetype: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
    },
  };
  const msg = messageWith(inner, "plain-doc");

  assert.equal(unwrapMessage(msg.message), inner);
  assertStoredMedia(msg, "document", "[Document] deck.pptx");
});

test("documentWithCaptionMessage unwraps to documentMessage and is not dropped", () => {
  const inner: proto.IMessage = {
    documentMessage: {
      fileName: "deck.pptx",
      caption: "Client pitch deck",
      mimetype: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
    },
  };
  const wrapped: proto.IMessage = {
    documentWithCaptionMessage: { message: inner },
  };
  const msg = messageWith(wrapped, "wrapped-doc");

  assert.equal(unwrapMessage(msg.message), inner);
  assertStoredMedia(msg, "document", "[Document] Client pitch deck");
});

test("ephemeralMessage-wrapped image unwraps and stores an image marker", () => {
  const inner: proto.IMessage = {
    imageMessage: { mimetype: "image/jpeg" },
  };
  const wrapped: proto.IMessage = {
    ephemeralMessage: { message: inner },
  };
  const msg = messageWith(wrapped, "ephemeral-image");

  assert.equal(unwrapMessage(msg.message), inner);
  assertStoredMedia(msg, "image", "[Image]");
});

test("viewOnceMessageV2-wrapped video unwraps and stores a video marker", () => {
  const inner: proto.IMessage = {
    videoMessage: { mimetype: "video/mp4" },
  };
  const wrapped: proto.IMessage = {
    viewOnceMessageV2: { message: inner },
  };
  const msg = messageWith(wrapped, "view-once-video");

  assert.equal(unwrapMessage(msg.message), inner);
  assertStoredMedia(msg, "video", "[Video]");
});

test("unknown message type stores an unsupported placeholder instead of being dropped", () => {
  const inner = {
    templateButtonReplyMessage: { selectedDisplayText: "Yes" },
  } as proto.IMessage;
  const msg = messageWith(inner, "unknown-template");

  const parsed = parseMessageForDb(msg);
  assert.notEqual(parsed, null);
  assert.equal(parsed?.content, "[Unsupported: templateButtonReplyMessage]");
});

test("videoMessage with gifPlayback stores a GIF marker", () => {
  const inner: proto.IMessage = {
    videoMessage: { mimetype: "video/mp4", gifPlayback: true, caption: "loop" },
  };
  const msg = messageWith(inner, "gif-video");

  assertStoredMedia(msg, "gif", "[GIF] loop");
});
