import { describe, it, expect, vi } from "vitest";
import { Prisma } from "@nexus/db";
import { TRPCError } from "@trpc/server";

// We need to stub out the prisma client import used by trpc.ts before importing
vi.mock("@nexus/db", async (importOriginal) => {
  const original = await importOriginal<typeof import("@nexus/db")>();
  return {
    ...original,
    prisma: {
      systemRoleConfig: { findMany: vi.fn(async () => []) },
    },
  };
});

// eslint-disable-next-line import/first
import { mapPrismaError } from "../trpc.js";

function makePrismaError(code: string): Prisma.PrismaClientKnownRequestError {
  return new Prisma.PrismaClientKnownRequestError("test message", {
    code,
    clientVersion: "test",
  });
}

describe("mapPrismaError", () => {
  it("maps P2002 (unique constraint) to CONFLICT", () => {
    const err = makePrismaError("P2002");
    const result = mapPrismaError(err);
    expect(result).toBeInstanceOf(TRPCError);
    expect(result.code).toBe("CONFLICT");
    expect(result.message).toBe("A record with this value already exists.");
  });

  it("maps P2025 (record not found) to NOT_FOUND", () => {
    const err = makePrismaError("P2025");
    const result = mapPrismaError(err);
    expect(result).toBeInstanceOf(TRPCError);
    expect(result.code).toBe("NOT_FOUND");
    expect(result.message).toBe("The requested record was not found.");
  });

  it("maps P2003 (foreign key constraint) to BAD_REQUEST", () => {
    const err = makePrismaError("P2003");
    const result = mapPrismaError(err);
    expect(result).toBeInstanceOf(TRPCError);
    expect(result.code).toBe("BAD_REQUEST");
    expect(result.message).toBe("A referenced record does not exist.");
  });

  it("maps an unknown Prisma code (P9999) to INTERNAL_SERVER_ERROR", () => {
    const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
    const err = makePrismaError("P9999");
    const result = mapPrismaError(err);
    expect(result).toBeInstanceOf(TRPCError);
    expect(result.code).toBe("INTERNAL_SERVER_ERROR");
    expect(result.message).toBe("A database error occurred.");
    expect(consoleSpy).toHaveBeenCalledWith("[Prisma error]", "P9999", "test message");
    consoleSpy.mockRestore();
  });
});

describe("withPrismaErrors middleware (integration)", () => {
  it("passes through non-Prisma errors unchanged", async () => {
    // We test this by verifying mapPrismaError is only invoked for Prisma errors.
    // A plain Error should not be caught by mapPrismaError.
    const plain = new Error("network failure");
    // mapPrismaError only accepts PrismaClientKnownRequestError, so passing a plain
    // Error through the middleware would re-throw it. We verify the type guard here:
    expect(plain instanceof Prisma.PrismaClientKnownRequestError).toBe(false);
  });
});
