import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest } from "next/server";

const mockSession = {
  user: { id: "user-1", name: "Test", email: "t@t.com", tier: "free" },
};

const { mockRequireSession } = vi.hoisted(() => ({
  mockRequireSession: vi.fn(),
}));

vi.mock("@/lib/api-auth", () => ({
  requireSessionOrApiKey: mockRequireSession,
}));

vi.mock("@epicure/db", () => ({
  db: {
    delete: vi.fn(() => ({ where: vi.fn().mockResolvedValue(undefined) })),
    update: vi.fn(() => ({
      set: vi.fn(() => ({ where: vi.fn().mockResolvedValue(undefined) })),
    })),
  },
  recipes: { id: "id", authorId: "author_id", visibility: "visibility" },
  eq: vi.fn(),
  and: vi.fn(),
  inArray: vi.fn(),
}));

import { DELETE, PATCH } from "../route";

function makeRequest(method: string, body: unknown) {
  return new NextRequest(`http://localhost/api/v1/recipes/bulk`, {
    method,
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
}

beforeEach(() => {
  vi.clearAllMocks();
  mockRequireSession.mockResolvedValue({ session: mockSession, response: null });
});

describe("DELETE /api/v1/recipes/bulk", () => {
  it("returns 200 on valid ids", async () => {
    const res = await DELETE(makeRequest("DELETE", { ids: ["r1", "r2"] }));
    expect(res.status).toBe(200);
    const body = await res.json() as { ok: boolean };
    expect(body.ok).toBe(true);
  });

  it("returns 400 when ids is empty array", async () => {
    const res = await DELETE(makeRequest("DELETE", { ids: [] }));
    expect(res.status).toBe(400);
  });

  it("returns 400 when body is invalid", async () => {
    const res = await DELETE(makeRequest("DELETE", { notIds: "wrong" }));
    expect(res.status).toBe(400);
  });

  it("returns 401 when not authenticated", async () => {
    mockRequireSession.mockResolvedValue({
      session: null,
      response: new Response(JSON.stringify({ error: "Unauthorized" }), { status: 401 }),
    });
    const res = await DELETE(makeRequest("DELETE", { ids: ["r1"] }));
    expect(res.status).toBe(401);
  });
});

describe("PATCH /api/v1/recipes/bulk", () => {
  it("returns 200 on valid visibility update", async () => {
    const res = await PATCH(makeRequest("PATCH", { ids: ["r1"], visibility: "public" }));
    expect(res.status).toBe(200);
  });

  it("returns 400 when visibility is missing", async () => {
    const res = await PATCH(makeRequest("PATCH", { ids: ["r1"] }));
    expect(res.status).toBe(400);
  });

  it("returns 400 when ids is empty", async () => {
    const res = await PATCH(makeRequest("PATCH", { ids: [], visibility: "public" }));
    expect(res.status).toBe(400);
  });

  it("returns 401 when not authenticated", async () => {
    mockRequireSession.mockResolvedValue({
      session: null,
      response: new Response(JSON.stringify({ error: "Unauthorized" }), { status: 401 }),
    });
    const res = await PATCH(makeRequest("PATCH", { ids: ["r1"], visibility: "public" }));
    expect(res.status).toBe(401);
  });
});
