/**
 * Tests for GET /api/stripe-price
 * Price ID lookup for checkout
 */

jest.mock("@/lib/stripe-prices", () => ({
  getStripePriceId: jest.fn(),
}));

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

jest.mock("@/lib/errors", () => ({
  getErrorMessage: (e: unknown) => (e instanceof Error ? e.message : String(e)),
}));

jest.mock("@/lib/errors/checkout-errors", () => ({
  CheckoutErrorCode: {
    INVALID_CURRENCY: "INVALID_CURRENCY",
    MISSING_PLAN_DATA: "MISSING_PLAN_DATA",
    INVALID_BILLING_PERIOD: "INVALID_BILLING_PERIOD",
    PRICE_NOT_FOUND: "PRICE_NOT_FOUND",
    UNKNOWN_ERROR: "UNKNOWN_ERROR",
  },
  createCheckoutError: jest.fn(
    (code: string, _context?: Record<string, unknown>) => ({
      code,
      userMessage: `Error: ${code}`,
      userMessageAr: `Error: ${code}`,
      retryable: false,
      recoverySteps: [],
      recoveryStepsAr: [],
    }),
  ),
}));

import { NextRequest } from "next/server";
import { getStripePriceId } from "@/lib/stripe-prices";

describe("GET /api/stripe-price", () => {
  let GET: (req: NextRequest) => Promise<Response>;

  beforeAll(async () => {
    const mod = await import("@/app/api/stripe-price/route");
    GET = mod.GET;
  });

  beforeEach(() => {
    jest.clearAllMocks();
  });

  function createRequest(params: Record<string, string>): NextRequest {
    const url = new URL("http://localhost:9000/api/stripe-price");
    Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
    return new NextRequest(url);
  }

  it("returns 400 when tier is missing", async () => {
    const response = await GET(createRequest({ period: "monthly" }));
    const data = await response.json();

    expect(response.status).toBe(400);
    expect(data.code).toBe("MISSING_PLAN_DATA");
  });

  it("returns 400 when period is missing", async () => {
    const response = await GET(createRequest({ tier: "tier2" }));
    const data = await response.json();

    expect(response.status).toBe(400);
    expect(data.code).toBe("MISSING_PLAN_DATA");
  });

  it("returns 400 for invalid billing period", async () => {
    const response = await GET(
      createRequest({ tier: "tier2", period: "weekly" }),
    );
    const data = await response.json();

    expect(response.status).toBe(400);
    expect(data.code).toBe("INVALID_BILLING_PERIOD");
  });

  it("returns 400 for invalid currency", async () => {
    const response = await GET(
      createRequest({ tier: "tier2", period: "monthly", currency: "USD" }),
    );
    const data = await response.json();

    expect(response.status).toBe(400);
    expect(data.code).toBe("INVALID_CURRENCY");
  });

  it("returns 404 when price ID not found", async () => {
    (getStripePriceId as jest.Mock).mockResolvedValue(null);

    const response = await GET(
      createRequest({ tier: "tier99", period: "monthly" }),
    );
    const data = await response.json();

    expect(response.status).toBe(404);
    expect(data.code).toBe("PRICE_NOT_FOUND");
  });

  it("returns price ID for valid monthly request", async () => {
    (getStripePriceId as jest.Mock).mockResolvedValue("price_monthly_tier2");

    const response = await GET(
      createRequest({ tier: "tier2", period: "monthly" }),
    );
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.priceId).toBe("price_monthly_tier2");
    expect(data.tier).toBe("tier2");
    expect(data.period).toBe("monthly");
    expect(data.currency).toBe("QAR");
    expect(data.success).toBe(true);
  });

  it("returns price ID for valid yearly request", async () => {
    (getStripePriceId as jest.Mock).mockResolvedValue("price_yearly_tier3");

    const response = await GET(
      createRequest({ tier: "tier3", period: "yearly" }),
    );
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.priceId).toBe("price_yearly_tier3");
    expect(data.period).toBe("yearly");
  });

  it("defaults to QAR currency when not specified", async () => {
    (getStripePriceId as jest.Mock).mockResolvedValue("price_default");

    await GET(createRequest({ tier: "tier2", period: "monthly" }));

    expect(getStripePriceId).toHaveBeenCalledWith("tier2", "monthly", "QAR");
  });

  it("returns 500 on unexpected errors", async () => {
    (getStripePriceId as jest.Mock).mockRejectedValue(
      new Error("Unexpected DB error"),
    );

    const response = await GET(
      createRequest({ tier: "tier2", period: "monthly" }),
    );
    const data = await response.json();

    expect(response.status).toBe(500);
    expect(data.code).toBe("UNKNOWN_ERROR");
  });
});
