import { describe, expect, it } from "vitest";

import { ChatMessage, ChatSendResponse } from "@/data/dto/chat";

import {
  buildChatMediaCacheKey,
  fallbackChatMediaMimeType,
  getMessageMediaTargets,
  getSendResponseMediaTargets,
  uniqueMediaTargets,
} from "../chat_media_cache_helpers";

function makeMessage(
  overrides: Partial<Parameters<typeof ChatMessage.from>[0]> = {},
): ChatMessage {
  return ChatMessage.from({
    id: "msg-1",
    role: "assistant",
    type: "image",
    content: "",
    createdAt: "2026-06-30T00:00:00.000Z",
    audioUrl: null,
    image: { type: null, url: null },
    lockDetail: {
      locked: false,
      showContent: true,
      showUpgrade: false,
      reason: null,
      hint: null,
      detail: null,
    },
    ...overrides,
  });
}

function makeResponse(
  overrides: Partial<Parameters<typeof ChatSendResponse.from>[0]> = {},
): ChatSendResponse {
  return ChatSendResponse.from({
    reply: "",
    audioUrl: "",
    messageId: "msg-1",
    isGuest: false,
    timestamp: 1782356425363,
    image: { type: null, url: null },
    lockDetail: {
      locked: false,
      showContent: true,
      showUpgrade: false,
      reason: null,
      hint: null,
      detail: null,
    },
    ...overrides,
  });
}

describe("chat media cache helpers", () => {
  it("builds owner-scoped media cache keys", () => {
    expect(
      buildChatMediaCacheKey({
        ownerKey: "user:u1",
        messageId: "msg-1",
        kind: "image",
      }),
    ).toBe("user:u1:msg-1:image");
  });

  it("extracts cacheable media targets from history messages", () => {
    expect(
      getMessageMediaTargets(
        makeMessage({
          audioUrl: "https://example.com/a.mp3",
          image: { type: "jpg", url: "https://example.com/a.jpg" },
        }),
      ),
    ).toEqual([
      {
        messageId: "msg-1",
        kind: "image",
        remoteUrl: "https://example.com/a.jpg",
      },
      {
        messageId: "msg-1",
        kind: "audio",
        remoteUrl: "https://example.com/a.mp3",
      },
    ]);
  });

  it("ignores empty message ids and non-remote media urls", () => {
    expect(
      getSendResponseMediaTargets(
        makeResponse({
          messageId: "",
          audioUrl: "https://example.com/a.mp3",
          image: { type: "png", url: "data:image/png;base64,abc" },
        }),
      ),
    ).toEqual([]);
  });

  it("deduplicates media targets", () => {
    expect(
      uniqueMediaTargets([
        { messageId: "msg-1", kind: "image", remoteUrl: "https://x/a.jpg" },
        { messageId: "msg-1", kind: "image", remoteUrl: "https://x/a.jpg" },
        { messageId: "msg-1", kind: "audio", remoteUrl: "https://x/a.jpg" },
      ]),
    ).toEqual([
      { messageId: "msg-1", kind: "image", remoteUrl: "https://x/a.jpg" },
      { messageId: "msg-1", kind: "audio", remoteUrl: "https://x/a.jpg" },
    ]);
  });

  it("provides fallback mime types", () => {
    expect(fallbackChatMediaMimeType("image")).toBe("image/*");
    expect(fallbackChatMediaMimeType("audio")).toBe("audio/mpeg");
  });
});
