import { describe, it, expect, beforeEach } from "vitest";
import { ContactList } from "@prisma/client";
import { InMemoryContactListsRepository } from "../repositories/in-memory-contact-lists-repository";
import { GetContactListsPaginatedUseCase } from "./get-contact-lists-paginated-use-case";

let contactListsRepository: InMemoryContactListsRepository;
let sut: GetContactListsPaginatedUseCase;

function makeList(overrides: Partial<ContactList> = {}): ContactList {
  return {
    id: `list-${Math.random()}`,
    name: "Lista",
    description: null,
    marketingChannel: "EMAIL",
    userId: "user-1",
    createdAt: new Date(),
    updatedAt: new Date(),
    ...overrides,
  };
}

describe("Get Contact Lists Paginated Use Case", () => {
  beforeEach(() => {
    contactListsRepository = new InMemoryContactListsRepository();
    sut = new GetContactListsPaginatedUseCase(contactListsRepository);
  });

  it("counts only contacts with ACTIVE status as active contacts for a list", async () => {
    contactListsRepository.items.push(makeList({ id: "list-1", name: "Saldo Clube A+" }));
    contactListsRepository.contacts.push(
      { id: "c1", status: "ACTIVE" },
      { id: "c2", status: "ACTIVE" },
      { id: "c3", status: "BOUNCED" },
      { id: "c4", status: "UNSUBSCRIBED" }
    );
    contactListsRepository.memberships.push(
      { contactId: "c1", listId: "list-1" },
      { contactId: "c2", listId: "list-1" },
      { contactId: "c3", listId: "list-1" },
      { contactId: "c4", listId: "list-1" }
    );

    const result = await sut.execute({ userId: "user-1", page: 1, pageSize: 20 });

    expect(result.items).toHaveLength(1);
    expect(result.items[0].activeContactsCount).toBe(2);
  });

  it("filters by search", async () => {
    contactListsRepository.items.push(makeList({ id: "list-1", name: "Clientes VIP" }));
    contactListsRepository.items.push(makeList({ id: "list-2", name: "Newsletter Geral" }));

    const result = await sut.execute({ userId: "user-1", page: 1, pageSize: 20, search: "vip" });

    expect(result.total).toBe(1);
    expect(result.items[0].id).toBe("list-1");
  });

  it("filters by marketingChannel", async () => {
    contactListsRepository.items.push(makeList({ id: "list-1", marketingChannel: "EMAIL" }));
    contactListsRepository.items.push(makeList({ id: "list-2", marketingChannel: "SMS" }));

    const result = await sut.execute({ userId: "user-1", page: 1, pageSize: 20, marketingChannel: "SMS" });

    expect(result.total).toBe(1);
    expect(result.items[0].id).toBe("list-2");
  });

  it("filters by createdAt range", async () => {
    contactListsRepository.items.push(makeList({ id: "list-1", createdAt: new Date("2026-01-05") }));
    contactListsRepository.items.push(makeList({ id: "list-2", createdAt: new Date("2026-02-15") }));
    contactListsRepository.items.push(makeList({ id: "list-3", createdAt: new Date("2026-03-25") }));

    const result = await sut.execute({
      userId: "user-1",
      page: 1,
      pageSize: 20,
      createdFrom: new Date("2026-02-01"),
      createdTo: new Date("2026-03-01"),
    });

    expect(result.total).toBe(1);
    expect(result.items[0].id).toBe("list-2");
  });

  it("paginates results and reports total independent of the page size", async () => {
    for (let i = 1; i <= 25; i++) {
      contactListsRepository.items.push(makeList({ id: `list-${i}` }));
    }

    const page1 = await sut.execute({ userId: "user-1", page: 1, pageSize: 10 });
    expect(page1.items).toHaveLength(10);
    expect(page1.total).toBe(25);

    const page3 = await sut.execute({ userId: "user-1", page: 3, pageSize: 10 });
    expect(page3.items).toHaveLength(5);
  });
});
