import { describe, it, expect, beforeEach } from "vitest";
import { InMemoryContactListsRepository } from "../repositories/in-memory-contact-lists-repository";
import { InMemoryContactsRepository } from "../repositories/in-memory-contacts-repository";
import { DeleteContactListUseCase } from "./delete-contact-list-use-case";
import { AppError } from "@/core/errors/app-error";

let contactListsRepository: InMemoryContactListsRepository;
let contactsRepository: InMemoryContactsRepository;
let sut: DeleteContactListUseCase;

describe("Delete Contact List Use Case", () => {
  beforeEach(() => {
    contactListsRepository = new InMemoryContactListsRepository();
    contactsRepository = new InMemoryContactsRepository();
    sut = new DeleteContactListUseCase(contactListsRepository, contactsRepository);
  });

  it("should be able to delete a contact list", async () => {
    const created = await contactListsRepository.create({ name: "Lista A", userId: "user-1" });

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

    expect(result.success).toBe(true);
    expect(contactListsRepository.items).toHaveLength(0);
  });

  it("should delete contacts that belong exclusively to the deleted list", async () => {
    const list = await contactListsRepository.create({ name: "Lista A", userId: "user-1" });

    // Contatos exclusivos da lista
    await contactsRepository.createMany(["a@test.com", "b@test.com"]);
    const [contactA, contactB] = contactsRepository.items;
    contactsRepository.listMemberships.push(
      { contactId: contactA.id, listId: list.id, listName: list.name },
      { contactId: contactB.id, listId: list.id, listName: list.name }
    );

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

    expect(result.deletedContactsCount).toBe(2);
    expect(contactsRepository.items).toHaveLength(0);
  });

  it("should NOT delete contacts that also belong to other lists", async () => {
    const listA = await contactListsRepository.create({ name: "Lista A", userId: "user-1" });
    const listB = await contactListsRepository.create({ name: "Lista B", userId: "user-1" });

    await contactsRepository.createMany(["shared@test.com"]);
    const [sharedContact] = contactsRepository.items;
    // O contato está em AMBAS as listas
    contactsRepository.listMemberships.push(
      { contactId: sharedContact.id, listId: listA.id, listName: listA.name },
      { contactId: sharedContact.id, listId: listB.id, listName: listB.name }
    );

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

    expect(result.deletedContactsCount).toBe(0);
    expect(contactsRepository.items).toHaveLength(1); // contato preservado
  });

  it("should not allow deleting another user's list", async () => {
    const created = await contactListsRepository.create({ name: "Lista A", userId: "user-1" });

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