import { describe, it, expect, beforeEach } from "vitest";
import { InMemorySendersRepository } from "@/modules/senders/repositories/in-memory-senders-repository";
import { InMemoryMailProvider } from "../providers/in-memory-mail-provider";
import { SendTestCampaignUseCase } from "./send-test-campaign-use-case";
import { AppError } from "@/core/errors/app-error";

let sendersRepository: InMemorySendersRepository;
let mailProvider: InMemoryMailProvider;
let sut: SendTestCampaignUseCase;

describe("Send Test Campaign Use Case", () => {
  beforeEach(() => {
    sendersRepository = new InMemorySendersRepository();
    mailProvider = new InMemoryMailProvider();
    sut = new SendTestCampaignUseCase(sendersRepository, () => mailProvider);
  });

  it("should send a test email using the current editor content", async () => {
    const sender = await sendersRepository.create({
      name: "John Doe",
      fromEmail: "john@example.com",
      provider: "SMTP",
      smtpHost: "smtp.example.com",
      smtpPort: 587,
      smtpUser: "john@example.com",
      userId: "user-1",
      encryptedPass: "encrypted-secret",
    });

    const result = await sut.execute({
      userId: "user-1",
      body: {
        subject: "Confira as novidades",
        htmlBody: "<p>Hello World</p>",
        senderId: sender.id,
        testEmail: "reviewer@example.com",
      },
    });

    expect(result.success).toBe(true);
    expect(mailProvider.sentEmails).toHaveLength(1);
    expect(mailProvider.sentEmails[0].to).toEqual("reviewer@example.com");
    expect(mailProvider.sentEmails[0].subject).toEqual("[TESTE] Confira as novidades");
  });

  it("should include the open-tracking pixel for non-SES senders", async () => {
    const sender = await sendersRepository.create({
      name: "John Doe",
      fromEmail: "john@example.com",
      provider: "SMTP",
      smtpHost: "smtp.example.com",
      smtpPort: 587,
      smtpUser: "john@example.com",
      userId: "user-1",
      encryptedPass: "encrypted-secret",
    });

    await sut.execute({
      userId: "user-1",
      body: {
        subject: "Confira as novidades",
        htmlBody: "<p>Hello World</p>",
        senderId: sender.id,
        testEmail: "reviewer@example.com",
      },
    });

    expect(mailProvider.sentEmails[0].html).toContain("/api/track/open/");
  });

  it("should not inject a second pixel for SES senders", async () => {
    const sender = await sendersRepository.create({
      name: "John Doe",
      fromEmail: "john@example.com",
      provider: "SES",
      userId: "user-1",
    });

    await sut.execute({
      userId: "user-1",
      body: {
        subject: "Confira as novidades",
        htmlBody: "<p>Hello World</p>",
        senderId: sender.id,
        testEmail: "reviewer@example.com",
      },
    });

    expect(mailProvider.sentEmails[0].html).not.toContain("/api/track/open/");
  });

  it("should not allow sending a test through another user's sender", async () => {
    const sender = await sendersRepository.create({
      name: "John Doe",
      fromEmail: "john@example.com",
      provider: "SMTP",
      smtpHost: "smtp.example.com",
      smtpPort: 587,
      smtpUser: "john@example.com",
      userId: "user-1",
      encryptedPass: "encrypted-secret",
    });

    await expect(
      sut.execute({
        userId: "user-2",
        body: {
          subject: "Confira as novidades",
          htmlBody: "<p>Hello World</p>",
          senderId: sender.id,
          testEmail: "reviewer@example.com",
        },
      })
    ).rejects.toBeInstanceOf(AppError);
  });

  it("should propagate a mail provider failure instead of reporting false success", async () => {
    const sender = await sendersRepository.create({
      name: "John Doe",
      fromEmail: "john@example.com",
      provider: "SMTP",
      smtpHost: "smtp.example.com",
      smtpPort: 587,
      smtpUser: "john@example.com",
      userId: "user-1",
      encryptedPass: "encrypted-secret",
    });

    mailProvider.shouldFail = true;

    await expect(
      sut.execute({
        userId: "user-1",
        body: {
          subject: "Confira as novidades",
          htmlBody: "<p>Hello World</p>",
          senderId: sender.id,
          testEmail: "reviewer@example.com",
        },
      })
    ).rejects.toBeInstanceOf(AppError);
  });
});
