import { describe, it, expect, beforeEach, vi } from "vitest";

// Mock marketplace-billing module (the route now delegates to it)
const mockGetOperatorEarnings = vi.fn();
vi.mock("@/lib/marketplace-billing", () => ({
  getOperatorEarnings: (...args: unknown[]) => mockGetOperatorEarnings(...args),
}));

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

vi.mock("@/lib/logger", () => ({
  logger: { info: vi.fn(), error: vi.fn(), warn: vi.fn() },
}));

import { auth } from "@/lib/auth";

describe("GET /api/dashboard/operator/earnings", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns 401 when not authenticated", async () => {
    vi.mocked(auth).mockResolvedValue(null as never);

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    const request = new Request("http://localhost/api/dashboard/operator/earnings");
    const response = await GET(request);

    expect(response.status).toBe(401);
    expect(mockGetOperatorEarnings).not.toHaveBeenCalled();
  });

  it("returns earnings summary with default 30-day period", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    mockGetOperatorEarnings.mockResolvedValue({
      totalRevenue: 0.30,
      operatorShare: 0.24,
      platformFee: 0.06,
      totalRequests: 2,
      periodDays: 30,
      dailyAverage: 0.008,
      firstBookingAt: "2026-03-05T10:00:00.000Z",
      lifetimeRequests: 5,
    });

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    const request = new Request("http://localhost/api/dashboard/operator/earnings");
    const response = await GET(request);
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.totalRevenue).toBeCloseTo(0.30);
    expect(data.operatorShare).toBeCloseTo(0.24);
    expect(data.platformFee).toBeCloseTo(0.06);
    expect(data.totalRequests).toBe(2);
    expect(data.periodDays).toBe(30);
    expect(data.dailyAverage).toBeCloseTo(0.008);
    expect(data.firstBookingAt).toBe("2026-03-05T10:00:00.000Z");
    expect(data.lifetimeRequests).toBe(5);
    expect(mockGetOperatorEarnings).toHaveBeenCalledWith("user-1", 30);
  });

  it("returns null firstBookingAt and zero lifetimeRequests for new operators", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-new" } } as never);
    mockGetOperatorEarnings.mockResolvedValue({
      totalRevenue: 0,
      operatorShare: 0,
      platformFee: 0,
      totalRequests: 0,
      periodDays: 30,
      dailyAverage: 0,
      firstBookingAt: null,
      lifetimeRequests: 0,
    });

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    const request = new Request("http://localhost/api/dashboard/operator/earnings");
    const response = await GET(request);
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.firstBookingAt).toBeNull();
    expect(data.lifetimeRequests).toBe(0);
  });

  it("returns zeros when no earnings exist", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    mockGetOperatorEarnings.mockResolvedValue({
      totalRevenue: 0,
      operatorShare: 0,
      platformFee: 0,
      totalRequests: 0,
      periodDays: 30,
      dailyAverage: 0,
    });

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    const request = new Request("http://localhost/api/dashboard/operator/earnings");
    const response = await GET(request);
    const data = await response.json();

    expect(data.totalRevenue).toBe(0);
    expect(data.operatorShare).toBe(0);
    expect(data.totalRequests).toBe(0);
    expect(data.periodDays).toBe(30);
  });

  it("respects custom period query param", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    mockGetOperatorEarnings.mockResolvedValue({
      totalRevenue: 1.0,
      operatorShare: 0.80,
      platformFee: 0.20,
      totalRequests: 10,
      periodDays: 7,
      dailyAverage: 0.114,
    });

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    const request = new Request(
      "http://localhost/api/dashboard/operator/earnings?period=7",
    );
    const response = await GET(request);
    const data = await response.json();

    expect(data.periodDays).toBe(7);
    expect(mockGetOperatorEarnings).toHaveBeenCalledWith("user-1", 7);
  });

  it("ignores invalid period param and defaults to 30", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    mockGetOperatorEarnings.mockResolvedValue({
      totalRevenue: 0,
      operatorShare: 0,
      platformFee: 0,
      totalRequests: 0,
      periodDays: 30,
      dailyAverage: 0,
    });

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    const request = new Request(
      "http://localhost/api/dashboard/operator/earnings?period=abc",
    );
    const response = await GET(request);

    expect(response.status).toBe(200);
    expect(mockGetOperatorEarnings).toHaveBeenCalledWith("user-1", 30);
  });

  it("clamps period to max 365 days", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    mockGetOperatorEarnings.mockResolvedValue({
      totalRevenue: 0,
      operatorShare: 0,
      platformFee: 0,
      totalRequests: 0,
      periodDays: 30,
      dailyAverage: 0,
    });

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    // period=999 exceeds max 365, should fall back to default 30
    const request = new Request(
      "http://localhost/api/dashboard/operator/earnings?period=999",
    );
    const response = await GET(request);

    expect(response.status).toBe(200);
    expect(mockGetOperatorEarnings).toHaveBeenCalledWith("user-1", 30);
  });

  it("returns 500 on service error", async () => {
    vi.mocked(auth).mockResolvedValue({ user: { id: "user-1" } } as never);
    mockGetOperatorEarnings.mockRejectedValue(new Error("DB down"));

    const { GET } = await import(
      "@/app/api/dashboard/operator/earnings/route"
    );
    const request = new Request("http://localhost/api/dashboard/operator/earnings");
    const response = await GET(request);

    expect(response.status).toBe(500);
  });
});
