import { describe, it, expect, vi, beforeEach } from "vitest";
import { prismaMock, resetPrismaMock } from "@/__tests__/helpers/prisma-mock";
import { createRequest, parseJsonResponse } from "@/__tests__/helpers/api-test-utils";
import { TEST_USER } from "@/__tests__/helpers/fixtures";

vi.mock("bcryptjs", () => ({
  default: { hash: vi.fn().mockResolvedValue("$2a$10$hashed") },
}));

import { POST } from "./route";

beforeEach(() => {
  resetPrismaMock();
});

describe("POST /api/auth/register", () => {
  it("registers a new user successfully", async () => {
    prismaMock.user.create.mockResolvedValue({
      ...TEST_USER,
      id: "new-user",
      username: "newuser",
      avatar: "🐱",
    } as never);

    const req = createRequest("/api/auth/register", {
      method: "POST",
      body: { username: "newuser", password: "password123" },
    });
    const res = await POST(req, { params: Promise.resolve({}) });
    const { status, data } = await parseJsonResponse(res);

    expect(status).toBe(200);
    expect(data.username).toBe("newuser");
    expect(data.id).toBe("new-user");
    expect(data.avatar).toBe("🐱");
  });

  it("uses custom avatar if provided", async () => {
    prismaMock.user.create.mockResolvedValue({
      ...TEST_USER,
      avatar: "🦊",
    } as never);

    const req = createRequest("/api/auth/register", {
      method: "POST",
      body: { username: "newuser", password: "password123", avatar: "🦊" },
    });
    const res = await POST(req, { params: Promise.resolve({}) });
    const { data } = await parseJsonResponse(res);

    expect(data.avatar).toBe("🦊");
  });

  it("returns 400 when username is missing", async () => {
    const req = createRequest("/api/auth/register", {
      method: "POST",
      body: { password: "password123" },
    });
    const res = await POST(req, { params: Promise.resolve({}) });
    expect(res.status).toBe(400);
  });

  it("returns 400 when password is missing", async () => {
    const req = createRequest("/api/auth/register", {
      method: "POST",
      body: { username: "testuser" },
    });
    const res = await POST(req, { params: Promise.resolve({}) });
    expect(res.status).toBe(400);
  });

  it("returns 400 when username too short", async () => {
    const req = createRequest("/api/auth/register", {
      method: "POST",
      body: { username: "a", password: "password123" },
    });
    const res = await POST(req, { params: Promise.resolve({}) });
    expect(res.status).toBe(400);
  });

  it("returns 400 when password too short", async () => {
    const req = createRequest("/api/auth/register", {
      method: "POST",
      body: { username: "testuser", password: "12345" },
    });
    const res = await POST(req, { params: Promise.resolve({}) });
    expect(res.status).toBe(400);
  });

  it("returns 409 when username already exists", async () => {
    const { Prisma } = await import("@prisma/client");
    prismaMock.user.create.mockRejectedValue(
      new Prisma.PrismaClientKnownRequestError("Unique constraint", {
        code: "P2002",
        clientVersion: "5.0.0",
      }),
    );

    const req = createRequest("/api/auth/register", {
      method: "POST",
      body: { username: "existing", password: "password123" },
    });
    const res = await POST(req, { params: Promise.resolve({}) });
    expect(res.status).toBe(409);
  });
});
