import { describe, it, expect } from "vitest";
import { signInController } from "@/interface-adapters/controllers/sign-in.controller";
import { signInUseCase } from "@/application/use-cases/sign-in.use-case";
import { MockUsersRepository } from "@/infrastructure/repositories/users.repository.mock";
import { MockAuthenticationService } from "@/infrastructure/services/authentication.service.mock";
import { InputParseError } from "@/entities/errors/common";
import { userFactory } from "@/__factories__/user.factory";
import { NoopRateLimit } from "@repo/core-shared/rate-limit";

describe("signInController", () => {
  it("returns a cookie on successful sign-in", async () => {
    const users = new MockUsersRepository([]);
    const auth = new MockAuthenticationService(users);
    const seedUser = userFactory.build({
      username: "alice",
      passwordHash: "hashed_testpassword",
    });
    await users.createUser(seedUser);

    const useCase = signInUseCase(users, auth, new NoopRateLimit());
    const controller = signInController(useCase);

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

  it("throws InputParseError on invalid input", async () => {
    const users = new MockUsersRepository([]);
    const auth = new MockAuthenticationService(users);
    const useCase = signInUseCase(users, auth, new NoopRateLimit());
    const controller = signInController(useCase);

    await expect(
      controller({ username: "ab" } as unknown),
    ).rejects.toBeInstanceOf(InputParseError);
  });

  it("throws InputParseError when input is not an object", async () => {
    const users = new MockUsersRepository([]);
    const auth = new MockAuthenticationService(users);
    const useCase = signInUseCase(users, auth, new NoopRateLimit());
    const controller = signInController(useCase);

    await expect(controller("garbage" as unknown)).rejects.toBeInstanceOf(
      InputParseError,
    );
  });
});
