import { beforeEach, describe, expect, it, vi } from "vitest";
import { prisma, __resetPrisma } from "../mocks/prisma";

const prismaPath = vi.hoisted(() => new URL("../../lib/prisma.ts", import.meta.url).pathname);
const monitoringPath = vi.hoisted(() => new URL("../../lib/monitoring.ts", import.meta.url).pathname);
const resendPath = vi.hoisted(() => new URL("../../lib/resend.ts", import.meta.url).pathname);
vi.mock(prismaPath, () => ({ prisma }));
vi.mock(monitoringPath, () => ({ logEvent: vi.fn(), logError: vi.fn() }));
vi.mock(resendPath, () => ({
  resend: { emails: { send: vi.fn().mockResolvedValue({ id: 'test' }) } },
  EMAIL_FROM: 'test@test.com',
}));

beforeEach(async () => {
  await vi.resetModules();
  __resetPrisma();
});

describe("Public API routes", () => {
  it("GET /api/products returns products", async () => {
    prisma.product.findMany.mockResolvedValueOnce([{ id: "p1" }]);
    const { GET } = await import("../../app/api/products/route");

    const res = await GET(new Request("http://localhost/api/products"));
    const data = await res.json();

    expect(res.status).toBe(200);
    expect(data).toHaveLength(1);
  });

  it("GET /api/products/[id] returns 404 when missing", async () => {
    prisma.product.findUnique.mockResolvedValueOnce(null);
    const { GET } = await import("../../app/api/products/[id]/route");

    const res = await GET(new Request("http://localhost/api/products/1"), {
      params: Promise.resolve({ id: "1" }),
    });

    expect(res.status).toBe(404);
  });

  it("GET /api/category-images returns list", async () => {
    prisma.categoryImage.findMany.mockResolvedValueOnce([{ id: "c1" }]);
    const { GET } = await import("../../app/api/category-images/route");

    const res = await GET();
    const data = await res.json();

    expect(res.status).toBe(200);
    expect(data).toHaveLength(1);
  });

  it("GET /api/reviews maps reviews", async () => {
    prisma.review.findMany.mockResolvedValueOnce([
      { id: "r1", productId: null, author: "A", rating: 5, text: "x", status: "approved", createdAt: new Date("2024-01-01T00:00:00Z") },
    ]);
    const { GET } = await import("../../app/api/reviews/route");

    const res = await GET();
    const data = await res.json();

    expect(res.status).toBe(200);
    expect(data[0].date).toContain("2024");
  });

  it("POST /api/reviews creates review", async () => {
    prisma.review.create.mockResolvedValueOnce({ id: "r1" });
    const { POST } = await import("../../app/api/reviews/route");

    const res = await POST(
      new Request("http://localhost/api/reviews", {
        method: "POST",
        body: JSON.stringify({ author: "A", text: "Hi", rating: 5 }),
        headers: { "content-type": "application/json" },
      })
    );

    expect(res.status).toBe(201);
  });

  it("POST /api/orders creates order", async () => {
    prisma.order.create.mockResolvedValueOnce({ id: "o1" });
    const { POST } = await import("../../app/api/orders/route");

    const res = await POST(
      new Request("http://localhost/api/orders", {
        method: "POST",
        body: JSON.stringify({
          customer: {
            name: "A",
            email: "a@example.com",
            phone: "1",
            address: "street",
            city: "Helsinki",
            zip: "00100",
            notes: null,
          },
          items: [],
          total: 10,
          shippingMethod: "postitus",
        }),
        headers: { "content-type": "application/json" },
      })
    );

    expect(res.status).toBe(201);
  });

  it("POST /api/monitoring returns ok", async () => {
    const { POST } = await import("../../app/api/monitoring/route");

    const res = await POST(
      new Request("http://localhost/api/monitoring", {
        method: "POST",
        body: JSON.stringify({ type: "web-vital" }),
        headers: { "content-type": "application/json" },
      })
    );

    const data = await res.json();
    expect(data.ok).toBe(true);
  });
});
