/**
 * Tests for testimonials (featured reviews) API routes
 * GET  /api/dashboard/reviews/testimonials - lists ALL reviews (featured first)
 * POST /api/dashboard/reviews/testimonials - toggle featured status
 * PUT  /api/dashboard/reviews/testimonials - reorder featured
 */

jest.mock("@/lib/convex-client", () => ({
  __esModule: true,
  convexQuery: jest.fn().mockResolvedValue(null),
  convexMutation: jest.fn().mockResolvedValue(null),
  convexAction: jest.fn().mockResolvedValue(null),
}));
jest.mock("@/lib/auth", () => ({ auth: jest.fn() }));
jest.mock("@/lib/utils/auth-helpers.util", () => ({
  getAuthenticatedUser: jest.fn(),
}));
jest.mock("@/lib/utils/organization-data", () => ({
  getEffectiveOwnerId: jest.fn((id: string) => id),
}));
jest.mock("@/lib/services/review-widget.service", () => ({
  listFeaturedReviews: jest.fn(),
  toggleFeaturedReview: jest.fn(),
  reorderFeaturedReviews: jest.fn(),
  generateEmbedCode: jest.fn(),
}));
jest.mock("@/lib/services/reviews.service", () => ({
  listReviews: jest.fn(),
}));
jest.mock("@/lib/data-source", () => ({
  getDataSource: jest.fn().mockReturnValue("convex"),
}));
jest.mock("@/lib/logger", () => ({
  logger: {
    scope: () => ({
      info: jest.fn(),
      error: jest.fn(),
      warn: jest.fn(),
      debug: jest.fn(),
    }),
  },
}));
jest.mock("@/lib/data-source", () => ({
  getDataSource: jest.fn(() => "prisma"),
}));
jest.mock("@/lib/validators/reviews.validator", () => ({
  ToggleFeaturedSchema: {
    safeParse: jest.fn((data: any) => {
      if (!data.reviewId) {
        return { success: false, error: { flatten: () => "reviewId is required" } };
      }
      return { success: true, data };
    }),
  },
  ReorderFeaturedSchema: {
    safeParse: jest.fn((data: any) => {
      if (!data.orderedIds || data.orderedIds.length === 0) {
        return { success: false, error: { flatten: () => "orderedIds is required" } };
      }
      return { success: true, data };
    }),
  },
}));

import { NextRequest } from "next/server";
import { getAuthenticatedUser } from "@/lib/utils/auth-helpers.util";
import * as widgetService from "@/lib/services/review-widget.service";
import { convexQuery, convexMutation } from "@/lib/convex-client";

const mockUser = { userId: "user-1", email: "test@test.com" };
const mockConvexQuery = convexQuery as jest.Mock;
const mockConvexMutation = convexMutation as jest.Mock;

function makeReq(url: string, method = "GET", body?: object) {
  const opts: RequestInit = { method };
  if (body) {
    opts.body = JSON.stringify(body);
    opts.headers = { "Content-Type": "application/json" };
  }
  return new NextRequest(`http://localhost:9000${url}`, opts);
}

// ─── GET /api/dashboard/reviews/testimonials ────────────────────────────────

describe("GET /api/dashboard/reviews/testimonials", () => {
  let mod: typeof import("@/app/api/dashboard/reviews/testimonials/route");
  beforeAll(async () => {
    mod = await import("@/app/api/dashboard/reviews/testimonials/route");
  });
  beforeEach(() => jest.clearAllMocks());

  it("returns 401 when unauthenticated", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(null);
    const res = await mod.GET(makeReq("/api/dashboard/reviews/testimonials"));
    expect(res.status).toBe(401);
  });

  it("returns reviews from Convex sorted with featured first", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    const mockReviews = [
      {
        _id: "r1",
        customerName: "Alice",
        rating: 5,
        isFeatured: true,
        featuredOrder: 0,
        createdAt: new Date().toISOString(),
      },
      {
        _id: "r2",
        customerName: "Bob",
        rating: 4,
        isFeatured: true,
        featuredOrder: 1,
        createdAt: new Date().toISOString(),
      },
    ];
    mockConvexQuery.mockResolvedValue(mockReviews);

    const res = await mod.GET(makeReq("/api/dashboard/reviews/testimonials"));
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.success).toBe(true);
    expect(json.testimonials).toHaveLength(2);
    expect(json.testimonials[0].customerName).toBe("Alice");
  });

  it("returns empty list when no reviews", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    mockConvexQuery.mockResolvedValue([]);

    const res = await mod.GET(makeReq("/api/dashboard/reviews/testimonials"));
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.testimonials).toEqual([]);
  });
});

// ─── POST /api/dashboard/reviews/testimonials ───────────────────────────────

describe("POST /api/dashboard/reviews/testimonials", () => {
  let mod: typeof import("@/app/api/dashboard/reviews/testimonials/route");
  beforeAll(async () => {
    mod = await import("@/app/api/dashboard/reviews/testimonials/route");
  });
  beforeEach(() => jest.clearAllMocks());

  it("returns 401 when unauthenticated", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(null);
    const res = await mod.POST(
      makeReq("/api/dashboard/reviews/testimonials", "POST", {
        reviewId: "r1",
        featured: true,
      }),
    );
    expect(res.status).toBe(401);
  });

  it("pins a review as featured via Convex", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    mockConvexMutation.mockResolvedValue("r1");

    const res = await mod.POST(
      makeReq("/api/dashboard/reviews/testimonials", "POST", {
        reviewId: "r1",
        featured: true,
      }),
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.success).toBe(true);
  });

  it("unpins a featured review", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    mockConvexMutation.mockResolvedValue("r1");

    const res = await mod.POST(
      makeReq("/api/dashboard/reviews/testimonials", "POST", {
        reviewId: "r1",
        featured: false,
      }),
    );
    expect(res.status).toBe(200);
  });

  it("returns 400 for missing reviewId", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    const res = await mod.POST(
      makeReq("/api/dashboard/reviews/testimonials", "POST", {
        featured: true,
      }),
    );
    expect(res.status).toBe(400);
  });

  it("returns 500 on service error", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    // Both Convex path and fallback service must fail for 500
    mockConvexMutation.mockRejectedValue(new Error("Convex error"));
    (widgetService.toggleFeaturedReview as jest.Mock).mockRejectedValue(
      new Error("Service error"),
    );

    const res = await mod.POST(
      makeReq("/api/dashboard/reviews/testimonials", "POST", {
        reviewId: "nonexistent",
        featured: true,
      }),
    );
    expect(res.status).toBe(500);
  });
});

// ─── PUT /api/dashboard/reviews/testimonials (reorder) ──────────────────────

describe("PUT /api/dashboard/reviews/testimonials", () => {
  let mod: typeof import("@/app/api/dashboard/reviews/testimonials/route");
  beforeAll(async () => {
    mod = await import("@/app/api/dashboard/reviews/testimonials/route");
  });
  beforeEach(() => jest.clearAllMocks());

  it("returns 401 when unauthenticated", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(null);
    const res = await mod.PUT(
      makeReq("/api/dashboard/reviews/testimonials", "PUT", {
        orderedIds: ["r1", "r2"],
      }),
    );
    expect(res.status).toBe(401);
  });

  it("reorders featured reviews", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    (widgetService.reorderFeaturedReviews as jest.Mock).mockResolvedValue(
      undefined,
    );

    const orderedIds = ["r2", "r1", "r3"];
    const res = await mod.PUT(
      makeReq("/api/dashboard/reviews/testimonials", "PUT", {
        orderedIds,
      }),
    );
    expect(res.status).toBe(200);
    const json = await res.json();
    expect(json.success).toBe(true);
    expect(widgetService.reorderFeaturedReviews).toHaveBeenCalledWith(
      "user-1",
      orderedIds,
    );
  });

  it("returns 400 for empty orderedIds array", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    const res = await mod.PUT(
      makeReq("/api/dashboard/reviews/testimonials", "PUT", {
        orderedIds: [],
      }),
    );
    expect(res.status).toBe(400);
  });

  it("returns 400 for missing orderedIds", async () => {
    (getAuthenticatedUser as jest.Mock).mockResolvedValue(mockUser);
    const res = await mod.PUT(
      makeReq("/api/dashboard/reviews/testimonials", "PUT", {}),
    );
    expect(res.status).toBe(400);
  });
});
