import { describe, it, expect } from "vitest";
import { RecordingEventBus } from "@repo/core-testing/instrumentation";
import { signUpController } from "@/interface-adapters/controllers/sign-up.controller";
import { MockUsersRepository } from "@/infrastructure/repositories/users.repository.mock";
import { MockAuthenticationService } from "@/infrastructure/services/authentication.service.mock";
import { signUpUseCase } from "@/application/use-cases/sign-up.use-case";
import { InputParseError } from "@/entities/errors/common";
import { userFactory } from "@/__factories__/user.factory";

describe("signUpController", () => {
  it("returns a cookie on successful sign-up", async () => {
    const users = new MockUsersRepository([]);
    const auth = new MockAuthenticationService(users);
    const useCase = signUpUseCase(users, auth, new RecordingEventBus());
    const controller = signUpController(useCase);

    const result = await controller({
      username: "carol",
      password: "secret_password",
      confirmPassword: "secret_password",
    });
    expect(result.name).toBe("session");
    expect(result.value).toBeTruthy();
  });

  it("throws InputParseError when passwords do not match", async () => {
    const users = new MockUsersRepository([]);
    const auth = new MockAuthenticationService(users);
    const useCase = signUpUseCase(users, auth, new RecordingEventBus());
    const controller = signUpController(useCase);

    await expect(
      controller({
        username: "dave",
        password: "secret_password",
        confirmPassword: "different_password",
      }),
    ).rejects.toBeInstanceOf(InputParseError);
  });

  it("throws InputParseError when username is too short", async () => {
    const users = new MockUsersRepository([]);
    const auth = new MockAuthenticationService(users);
    await users.createUser(userFactory.build({ username: "alice" }));
    const useCase = signUpUseCase(users, auth, new RecordingEventBus());
    const controller = signUpController(useCase);

    await expect(
      controller({ username: "ab", password: "secret_password", confirmPassword: "secret_password" }),
    ).rejects.toBeInstanceOf(InputParseError);
  });
});
