import { describe, it, expect, beforeEach } from "vitest";
import bcrypt from "bcrypt";
import { InMemoryUsersRepository } from "../repositories/in-memory-users-repository";
import { AuthenticateUserUseCase } from "./authenticate-user-use-case";
import { AppError } from "@/core/errors/app-error";

let usersRepository: InMemoryUsersRepository;
let sut: AuthenticateUserUseCase;

describe("Authenticate User Use Case", () => {
  beforeEach(async () => {
    usersRepository = new InMemoryUsersRepository();
    sut = new AuthenticateUserUseCase(usersRepository);

    usersRepository.items.push({
      id: "user-1",
      name: "Test User",
      email: "user@example.com",
      passwordHash: await bcrypt.hash("correct-password", 6),
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  });

  it("should authenticate with valid credentials", async () => {
    const { user } = await sut.execute({
      body: { email: "user@example.com", password: "correct-password" },
    });

    expect(user.email).toEqual("user@example.com");
  });

  it("should reject an unknown email", async () => {
    await expect(
      sut.execute({ body: { email: "unknown@example.com", password: "correct-password" } })
    ).rejects.toBeInstanceOf(AppError);
  });

  it("should reject a wrong password", async () => {
    await expect(
      sut.execute({ body: { email: "user@example.com", password: "wrong-password" } })
    ).rejects.toBeInstanceOf(AppError);
  });

  it("should reject a malformed body", async () => {
    await expect(sut.execute({ body: { email: "not-an-email" } })).rejects.toBeInstanceOf(AppError);
  });
});
