import { describe, it, expect, beforeEach } from "vitest";
import { Contact, ContactStatus } from "@prisma/client";
import { InMemoryCampaignsRepository } from "../repositories/in-memory-campaigns-repository";
import { InMemoryCampaignLogsRepository } from "../repositories/in-memory-campaign-logs-repository";
import { InMemoryMailProvider } from "../providers/in-memory-mail-provider";
import { InMemorySuppressedEmailsRepository } from "@/modules/suppression/repositories/in-memory-suppressed-emails-repository";
import { RetryFailedCampaignUseCase } from "./retry-failed-campaign-use-case";
import { AppError } from "@/core/errors/app-error";

let campaignsRepository: InMemoryCampaignsRepository;
let campaignLogsRepository: InMemoryCampaignLogsRepository;
let suppressedEmailsRepository: InMemorySuppressedEmailsRepository;
let mailProvider: InMemoryMailProvider;
let sut: RetryFailedCampaignUseCase;

function makeContact(overrides: Partial<Contact> = {}): Contact {
  return {
    id: "contact-1",
    email: "contact@example.com",
    name: null,
    lastName: null,
    phone: null,
    bairro: null,
    cidade: null,
    uf: null,
    idioma: null,
    empresa: null,
    cep: null,
    codigoEstabelecimento: null,
    nomeEstabelecimento: null,
    cdate: null,
    tags: [],
    source: "MANUAL",
    status: ContactStatus.ACTIVE,
    createdAt: new Date(),
    updatedAt: new Date(),
    ...overrides,
  };
}

describe("Retry Failed Campaign Use Case", () => {
  beforeEach(() => {
    campaignsRepository = new InMemoryCampaignsRepository();
    campaignLogsRepository = new InMemoryCampaignLogsRepository();
    suppressedEmailsRepository = new InMemorySuppressedEmailsRepository();
    mailProvider = new InMemoryMailProvider();
    sut = new RetryFailedCampaignUseCase(
      campaignsRepository,
      campaignLogsRepository,
      suppressedEmailsRepository,
      () => mailProvider
    );
  });

  it("should be able to retry failed emails in campaign", async () => {
    const created = await campaignsRepository.create({
      title: "Test",
      subject: "Subject",
      htmlBody: "<p>Body</p>",
      createdById: "user-1",
    });

    const log = await campaignLogsRepository.upsertPending(created.id, "contact-1");
    await campaignLogsRepository.markFailed(log.id, "erro anterior");
    campaignLogsRepository.items[0].contact = makeContact();

    const result = await sut.execute({ id: created.id, userId: "user-1" });

    expect(result.retried).toEqual(1);
    expect(result.succeeded).toEqual(1);
    expect(result.failed).toEqual(0);
  });

  it("should not allow retrying another user's campaign", async () => {
    const created = await campaignsRepository.create({
      title: "Test",
      subject: "Subject",
      htmlBody: "<p>Body</p>",
      createdById: "user-1",
    });

    await expect(sut.execute({ id: created.id, userId: "user-2" })).rejects.toBeInstanceOf(AppError);
  });
});
