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

vi.mock("./db", () => ({
  addAttachment: vi.fn().mockResolvedValue(undefined),
  addMessage: vi.fn().mockResolvedValueOnce(100).mockResolvedValueOnce(101),
  createConversation: vi.fn(),
  getConversation: vi.fn().mockResolvedValue({ id: 42, userId: 1, title: "A saved thought" }),
  listConversations: vi.fn(),
  listMessages: vi.fn().mockResolvedValue([
    {
      id: 100,
      conversationId: 42,
      role: "user",
      content: "Summarize this.",
      createdAt: new Date(),
      attachments: [],
    },
  ]),
  renameConversation: vi.fn(),
}));

vi.mock("./storage", () => ({
  storagePut: vi.fn().mockResolvedValue({ key: "chat/1/brief.txt-abc", url: "/manus-storage/chat/1/brief.txt-abc" }),
}));

vi.mock("./_core/llm", () => ({
  invokeLLM: vi.fn().mockResolvedValue({
    choices: [{ message: { role: "assistant", content: "Here is a concise summary." } }],
  }),
}));

import { appRouter } from "./routers";
import type { TrpcContext } from "./_core/context";

function createContext(): TrpcContext {
  return {
    user: {
      id: 1,
      openId: "test-user",
      name: "Test User",
      email: "test@example.com",
      loginMethod: "test",
      role: "user",
      createdAt: new Date(),
      updatedAt: new Date(),
      lastSignedIn: new Date(),
    },
    req: {
      protocol: "https",
      get: (name: string) => (name.toLowerCase() === "host" ? "luma.test" : undefined),
      headers: {},
    } as TrpcContext["req"],
    res: {} as TrpcContext["res"],
  };
}

describe("chat.send", () => {
  it("returns the assistant response and accepts persisted attachment metadata", async () => {
    const caller = appRouter.createCaller(createContext());
    const result = await caller.chat.send({
      conversationId: 42,
      content: "Summarize this.",
      attachments: [
        {
          fileName: "brief.txt",
          mimeType: "text/plain",
          fileSize: 5,
          data: Buffer.from("hello").toString("base64"),
        },
      ],
    });

    expect(result).toMatchObject({
      conversationId: 42,
      userMessageId: 100,
      assistantMessageId: 101,
      content: "Here is a concise summary.",
    });

    const { addAttachment } = await import("./db");
    expect(addAttachment).toHaveBeenCalledWith(expect.objectContaining({
      userId: 1,
      conversationId: 42,
      messageId: 100,
      fileName: "brief.txt",
      fileSize: 5,
    }));
  });
});
