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

const mockSession = { user: { id: "user-1" } };

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

vi.mock("@/lib/webhooks", () => ({
  dispatchWebhook: vi.fn().mockResolvedValue(undefined),
}));

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

vi.mock("@epicure/db", () => ({
  db: {
    query: {
      webhooks: { findFirst: mockWebhookFindFirst },
      webhookDeliveries: { findFirst: mockDeliveryFindFirst },
    },
  },
  webhooks: { id: "id", userId: "user_id" },
  webhookDeliveries: { id: "id", webhookId: "webhook_id" },
  eq: vi.fn((a, b) => ({ a, b, op: "eq" })),
  and: vi.fn((...args) => ({ args, op: "and" })),
}));

const { requireDeveloper } = await import("@/lib/api-auth");
const { dispatchWebhook } = await import("@/lib/webhooks");
import { POST } from "../route";

const VALID_DELIVERY_ID = "11111111-1111-1111-1111-111111111111";

function makeRequest(body?: unknown) {
  return new NextRequest("http://localhost/api/v1/webhooks/wh-1/redeliver", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: body ? JSON.stringify(body) : undefined,
  });
}

const ctx = { params: Promise.resolve({ id: "wh-1" }) };

beforeEach(() => {
  vi.clearAllMocks();
  vi.mocked(requireDeveloper).mockResolvedValue({ session: mockSession as never, response: null });
  mockWebhookFindFirst.mockResolvedValue({ id: "wh-1" });
  mockDeliveryFindFirst.mockResolvedValue({
    id: VALID_DELIVERY_ID,
    event: "recipe.created",
    payload: { recipeId: "r-1" },
  });
});

describe("POST /api/v1/webhooks/[id]/redeliver", () => {
  it("returns 401 when not authenticated", async () => {
    vi.mocked(requireDeveloper).mockResolvedValue({
      session: null,
      response: new Response(JSON.stringify({ error: "Unauthorized" }), { status: 401 }),
    } as never);

    const res = await POST(makeRequest({ deliveryId: VALID_DELIVERY_ID }), ctx);
    expect(res.status).toBe(401);
  });

  it("returns 404 when the webhook does not belong to the caller", async () => {
    mockWebhookFindFirst.mockResolvedValue(undefined);
    const res = await POST(makeRequest({ deliveryId: VALID_DELIVERY_ID }), ctx);
    expect(res.status).toBe(404);
  });

  it("returns 400 when deliveryId is not a valid UUID", async () => {
    const res = await POST(makeRequest({ deliveryId: "not-a-uuid" }), ctx);
    expect(res.status).toBe(400);
  });

  it("returns 404 when the delivery is not found", async () => {
    mockDeliveryFindFirst.mockResolvedValue(undefined);
    const res = await POST(makeRequest({ deliveryId: VALID_DELIVERY_ID }), ctx);
    expect(res.status).toBe(404);
  });

  it("replays the delivery payload via dispatchWebhook", async () => {
    const res = await POST(makeRequest({ deliveryId: VALID_DELIVERY_ID }), ctx);
    expect(res.status).toBe(200);
    expect(dispatchWebhook).toHaveBeenCalledWith("user-1", "recipe.created", { recipeId: "r-1" });
  });
});
