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

const httpClientMock = vi.hoisted(() => vi.fn());

vi.mock("../http_client", () => ({
  httpClient: httpClientMock,
}));

import { PaymentApi } from "../payment_api";

describe("PaymentApi", () => {
  beforeEach(() => {
    httpClientMock.mockReset();
  });

  it("loads the complete public gift catalog for a character", async () => {
    httpClientMock.mockResolvedValue({
      success: true,
      data: {
        characterId: "elio",
        categories: [
          {
            category: "coffee",
            name: "Coffee",
            productCount: 1,
            imageUrl: null,
          },
        ],
        plans: [
          {
            planId: "tip_coffee_usd_19_99",
            planName: "Large Coffee",
            orderType: "tip",
            tipType: "coffee_large",
            category: "coffee",
            characterId: "elio",
            description: "Buy Elio a large coffee",
            imageUrl: null,
            amountCents: 1999,
            currency: "USD",
            autoRenew: false,
            isFirstRechargeOffer: false,
            firstRechargeDiscountPercent: 0,
            promotionType: null,
          },
        ],
      },
    });

    const response = await new PaymentApi().getGiftProducts("elio");

    expect(httpClientMock).toHaveBeenCalledWith(
      "/api/payment/gift-products",
      { query: { characterId: "elio" } },
    );
    expect(response.categories[0]?.category).toBe("coffee");
    expect(response.plans[0]?.planId).toBe("tip_coffee_usd_19_99");
  });

  it("posts the paid order id when loading the Tip message", async () => {
    httpClientMock.mockResolvedValue({
      success: true,
      data: {
        orderId: "pay_xxx",
        characterId: "elio",
        planId: "tip_coffee_usd_19_99",
        productName: "Large Coffee",
        tipCount: 1,
        poolIndex: 7,
        message: "Thank you for the thoughtful gift.",
      },
    });

    const response = await new PaymentApi().getTipMessage({
      orderId: "pay_xxx",
    });

    expect(httpClientMock).toHaveBeenCalledWith("/api/payment/tip-message", {
      method: "POST",
      body: { orderId: "pay_xxx" },
    });
    expect(response.message).toBe("Thank you for the thoughtful gift.");
  });

  it("accepts a server-issued offer before opening the subscription page", async () => {
    httpClientMock.mockResolvedValue({
      success: true,
      data: {
        commercialOfferId: "offer-1",
        planId: "vip_annual",
        subscriptionType: "vip",
        discountPercent: 30,
        pricePercent: 70,
        expiresAt: "2026-07-24T08:00:00+00:00",
        message: "I got it for you.",
        promotionType: "commercial_seven_discount",
      },
    });

    const response = await new PaymentApi().acceptCommercialOffer("offer-1");

    expect(httpClientMock).toHaveBeenCalledWith(
      "/api/payment/commercial-offers/offer-1/accept",
      { method: "POST" },
    );
    expect(response.discountPercent).toBe(30);
  });

  it("requests an offer-scoped plan catalog without changing the public call", async () => {
    httpClientMock.mockResolvedValue({ success: true, data: { plans: [] } });

    await new PaymentApi().getPlans("offer-1");

    expect(httpClientMock).toHaveBeenCalledWith("/api/payment/plans", {
      query: { commercialOfferId: "offer-1" },
    });
  });
});
