/**
 * Tests for Review Widget Service (Convex-backed)
 */

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/logger", () => ({
  logger: {
    info: jest.fn(),
    warn: jest.fn(),
    error: jest.fn(),
    debug: jest.fn(),
    scope: jest.fn().mockReturnValue({
      info: jest.fn(),
      warn: jest.fn(),
      error: jest.fn(),
      debug: jest.fn(),
    }),
  },
}));

import { convexQuery, convexMutation } from "@/lib/convex-client";
import {
  getWidgetSettings,
  upsertWidgetSettings,
  getPublicWidgetData,
} from "@/lib/services/review-widget.service";

const mockConvexQuery = convexQuery as jest.Mock;
const mockConvexMutation = convexMutation as jest.Mock;

describe("getWidgetSettings", () => {
  beforeEach(() => jest.clearAllMocks());

  it("returns existing settings when found", async () => {
    const mockSettings = {
      _id: "ws-1",
      userId: "user-1",
      businessName: "My Biz",
      primaryColor: "#ff0000",
      backgroundColor: "#ffffff",
      textColor: "#1e293b",
      showPoweredBy: true,
      createdAt: Date.now(),
      updatedAt: Date.now(),
    };
    mockConvexQuery.mockResolvedValueOnce(mockSettings);

    const result = await getWidgetSettings("user-1");
    expect(result.businessName).toBe("My Biz");
    expect(result.primaryColor).toBe("#ff0000");
    expect(mockConvexQuery).toHaveBeenCalledWith(
      "reviews/queries:getWidgetSettings",
      { userId: "user-1" },
    );
  });

  it("returns defaults when no settings exist", async () => {
    mockConvexQuery.mockResolvedValueOnce(null);

    const result = await getWidgetSettings("user-1");
    expect(result).toEqual({
      userId: "user-1",
      businessName: null,
      businessNameAr: null,
      logoUrl: null,
      primaryColor: "#10b981",
      backgroundColor: "#ffffff",
      textColor: "#1e293b",
      thankYouMessage: null,
      thankYouMessageAr: null,
      showPoweredBy: true,
      customCss: null,
    });
  });
});

describe("upsertWidgetSettings", () => {
  beforeEach(() => jest.clearAllMocks());

  it("creates new settings", async () => {
    const input = {
      businessName: "My Biz",
      primaryColor: "#10b981",
      backgroundColor: "#ffffff",
      textColor: "#1e293b",
      showPoweredBy: true,
    };
    // First call: convexMutation for upsert
    mockConvexMutation.mockResolvedValueOnce("ws-new-id");
    // Second call: convexQuery to re-fetch settings
    mockConvexQuery.mockResolvedValueOnce({
      _id: "ws-new-id",
      userId: "user-1",
      businessName: "My Biz",
      primaryColor: "#10b981",
      backgroundColor: "#ffffff",
      textColor: "#1e293b",
      showPoweredBy: true,
      createdAt: Date.now(),
      updatedAt: Date.now(),
    });

    const result = await upsertWidgetSettings("user-1", input);
    expect(result.businessName).toBe("My Biz");
    expect(mockConvexMutation).toHaveBeenCalledWith(
      "reviews/mutations:updateWidgetSettings",
      expect.objectContaining({
        userId: "user-1",
        businessName: "My Biz",
      }),
    );
  });

  it("updates existing settings", async () => {
    const input = {
      businessName: "Updated Biz",
      primaryColor: "#ff0000",
      backgroundColor: "#000000",
      textColor: "#ffffff",
      showPoweredBy: false,
    };
    mockConvexMutation.mockResolvedValueOnce("existing-id");
    mockConvexQuery.mockResolvedValueOnce({
      _id: "existing-id",
      userId: "user-1",
      businessName: "Updated Biz",
      primaryColor: "#ff0000",
      backgroundColor: "#000000",
      textColor: "#ffffff",
      showPoweredBy: false,
      createdAt: Date.now(),
      updatedAt: Date.now(),
    });

    const result = await upsertWidgetSettings("user-1", input);
    expect(result.businessName).toBe("Updated Biz");
  });
});

describe("getPublicWidgetData", () => {
  beforeEach(() => jest.clearAllMocks());

  it("returns data for a valid non-expired token", async () => {
    const mockRequest = {
      _id: "req-1",
      customerName: "John",
      language: "en",
      questions: [{ questionEn: "Q?", questionAr: "س؟" }],
      userId: "user-1",
      status: "PENDING",
      expiresAt: Date.now() + 86400000,
    };
    // First convexQuery: review request by token
    mockConvexQuery.mockResolvedValueOnce(mockRequest);

    const mockWidget = {
      _id: "ws-1",
      userId: "user-1",
      businessName: "Biz",
      primaryColor: "#10b981",
      backgroundColor: "#ffffff",
      textColor: "#1e293b",
      showPoweredBy: true,
      createdAt: Date.now(),
      updatedAt: Date.now(),
    };
    // Second convexQuery: widget settings
    mockConvexQuery.mockResolvedValueOnce(mockWidget);

    const result = await getPublicWidgetData("valid-token");
    expect(result).not.toBeNull();
    expect(result!.requestId).toBe("req-1");
    expect(result!.customerName).toBe("John");
    expect(result!.questions).toHaveLength(1);
    expect(result!.widget.businessName).toBe("Biz");
  });

  it("returns null for invalid/expired token", async () => {
    mockConvexQuery.mockResolvedValueOnce(null);

    const result = await getPublicWidgetData("invalid-token");
    expect(result).toBeNull();
  });

  it("returns default widget settings when no widget settings exist", async () => {
    mockConvexQuery.mockResolvedValueOnce({
      _id: "req-1",
      customerName: "John",
      language: "en",
      questions: [],
      userId: "user-1",
      status: "PENDING",
      expiresAt: Date.now() + 86400000,
    });
    // No widget settings found
    mockConvexQuery.mockResolvedValueOnce(null);

    const result = await getPublicWidgetData("valid-token");
    expect(result).not.toBeNull();
    expect(result!.widget.primaryColor).toBe("#10b981");
    expect(result!.widget.showPoweredBy).toBe(true);
  });
});
