/**
 * Server Pricing Suite
 *
 * The server — never the client — decides what a plan costs. These tests pin
 * the pure checkout builder against the shared price catalog (src/lib/billing/
 * pricing.ts): bogus plans fall back to annual, the catalog amounts (499 /
 * 3999 / 5999) are used verbatim when no Stripe Price ID is configured, and an
 * env Price ID wins when present. No real Stripe calls are made.
 */

import { describe, test, expect } from "./runner";
import { buildCheckoutParams } from "../../src/lib/billing/checkout";
import { PLAN_CONFIGS } from "../../src/lib/billing/pricing";

const user = { id: "usr_test_checkout_1" };

describe("ServerPricing — plan resolution", () => {
  test("unknown or missing plans fall back to annual", () => {
    expect(buildCheckoutParams(user, "enterprise-ultra", {}).metadata.plan).toBe("annual");
    expect(buildCheckoutParams(user, undefined, {}).metadata.plan).toBe("annual");
    expect(buildCheckoutParams(user, null, {}).metadata.plan).toBe("annual");
    expect(buildCheckoutParams(user, "", {}).metadata.plan).toBe("annual");
  });

  test("a bogus plan is charged the annual price, never an invented one", () => {
    const params = buildCheckoutParams(user, "FREE_FOREVER", {});
    expect(params.metadata.plan).toBe("annual");
    expect(params.lineItems[0].price_data?.unit_amount).toBe(PLAN_CONFIGS.annual.unitAmountMinor);
    expect(params.lineItems[0].price_data?.unit_amount).toBe(3999);
  });

  test("known plan ids resolve to themselves", () => {
    expect(buildCheckoutParams(user, "weekly", {}).metadata.plan).toBe("weekly");
    expect(buildCheckoutParams(user, "annual", {}).metadata.plan).toBe("annual");
    expect(buildCheckoutParams(user, "lifetime", {}).metadata.plan).toBe("lifetime");
  });
});

describe("ServerPricing — catalog amounts", () => {
  test("without an env Price ID, unit_amount is exactly the catalog value per plan", () => {
    expect(buildCheckoutParams(user, "weekly", {}).lineItems[0].price_data?.unit_amount).toBe(499);
    expect(buildCheckoutParams(user, "annual", {}).lineItems[0].price_data?.unit_amount).toBe(3999);
    expect(buildCheckoutParams(user, "lifetime", {}).lineItems[0].price_data?.unit_amount).toBe(5999);
  });

  test("the amounts stay pinned to PLAN_CONFIGS and never drift apart", () => {
    expect(buildCheckoutParams(user, "weekly", {}).lineItems[0].price_data?.unit_amount).toBe(
      PLAN_CONFIGS.weekly.unitAmountMinor
    );
    expect(buildCheckoutParams(user, "annual", {}).lineItems[0].price_data?.unit_amount).toBe(
      PLAN_CONFIGS.annual.unitAmountMinor
    );
    expect(buildCheckoutParams(user, "lifetime", {}).lineItems[0].price_data?.unit_amount).toBe(
      PLAN_CONFIGS.lifetime.unitAmountMinor
    );
  });

  test("a client-supplied amount cannot influence the charged price", () => {
    // The builder accepts no amount parameter; the body can only carry a plan
    // id, so the catalog amount is what gets charged no matter what else a
    // tampered request tries to inject.
    const params = buildCheckoutParams(user, "annual", {} as any);
    expect(params.lineItems[0].price_data?.unit_amount).toBe(PLAN_CONFIGS.annual.unitAmountMinor);
    expect(params.lineItems[0].price_data?.unit_amount).toBe(3999);
  });
});

describe("ServerPricing — env Price ID precedence", () => {
  test("a configured env Price ID wins and suppresses price_data entirely", () => {
    const weekly = buildCheckoutParams(user, "weekly", {
      STRIPE_WEEKLY_PRICE_ID: "price_weekly_test",
    });
    expect(weekly.lineItems[0].price).toBe("price_weekly_test");
    expect(weekly.lineItems[0].price_data).toBeUndefined();

    const annual = buildCheckoutParams(user, "annual", {
      STRIPE_ANNUAL_PRICE_ID: "price_annual_test",
    });
    expect(annual.lineItems[0].price).toBe("price_annual_test");
    expect(annual.lineItems[0].price_data).toBeUndefined();

    const lifetime = buildCheckoutParams(user, "lifetime", {
      STRIPE_LIFETIME_PRICE_ID: "price_lifetime_test",
    });
    expect(lifetime.lineItems[0].price).toBe("price_lifetime_test");
    expect(lifetime.lineItems[0].price_data).toBeUndefined();
  });

  test("the env Price ID comes from the plan's own catalog entry", () => {
    const weekly = buildCheckoutParams(user, "weekly", {
      [PLAN_CONFIGS.weekly.priceIdEnv]: "price_weekly_test",
    });
    expect(weekly.lineItems[0].price).toBe("price_weekly_test");
    expect(weekly.lineItems[0].price_data).toBeUndefined();
  });
});

describe("ServerPricing — subscription shape", () => {
  test("weekly is a subscription with a 3-day trial and weekly billing", () => {
    const params = buildCheckoutParams(user, "weekly", {});
    expect(params.mode).toBe("subscription");
    expect(params.subscriptionData?.trial_period_days).toBe(3);
    expect(params.subscriptionData?.metadata?.plan).toBe("weekly");
    expect(params.lineItems[0].price_data?.recurring?.interval).toBe("week");
  });

  test("annual is a subscription billed yearly, without any trial", () => {
    const params = buildCheckoutParams(user, "annual", {});
    expect(params.mode).toBe("subscription");
    expect(params.subscriptionData?.trial_period_days).toBeUndefined();
    expect(params.subscriptionData?.metadata?.plan).toBe("annual");
    expect(params.lineItems[0].price_data?.recurring?.interval).toBe("year");
  });

  test("lifetime is a one-off payment without subscription data", () => {
    const params = buildCheckoutParams(user, "lifetime", {});
    expect(params.mode).toBe("payment");
    expect(params.subscriptionData).toBeUndefined();
    expect(params.lineItems[0].price_data?.recurring).toBeUndefined();
  });

  test("only the weekly pass ever carries a trial", () => {
    const plans = ["weekly", "annual", "lifetime"] as const;
    for (const plan of plans) {
      const params = buildCheckoutParams(user, plan, {});
      const trial = params.subscriptionData?.trial_period_days;
      expect(trial).toBe(plan === "weekly" ? 3 : undefined);
    }
  });
});

describe("ServerPricing — metadata & reference", () => {
  test("metadata always carries the resolved plan and the user id", () => {
    for (const plan of ["weekly", "annual", "lifetime"]) {
      const params = buildCheckoutParams(user, plan, {});
      expect(params.metadata.plan).toBe(plan);
      expect(params.metadata.userId).toBe(user.id);
      expect(params.clientReferenceId).toBe(user.id);
    }
  });

  test("the fallback plan keeps the authenticated user's id attached", () => {
    const params = buildCheckoutParams(user, "hacker-plan", {});
    expect(params.metadata.plan).toBe("annual");
    expect(params.metadata.userId).toBe(user.id);
    expect(params.clientReferenceId).toBe(user.id);
  });
});
