// src/lib/mcp/entitlements.test.ts — org add-on entitlement resolution (postgres).
// Integration tests — require Postgres + the test DB migrated. Skipped unless DB_TESTS=1.
// Verifies the trial-derived MCP entitlement: an org in an app-level trial
// (trialEndsAt in the future, no active Stripe sub) gets the checklist_mcp
// add-on WITHOUT any org_addons row — the access is computed from the billing
// status, never stored. Other add-ons (seranking_byok) stay row-only.
import { beforeEach, describe, expect, mock, test } from "bun:test";
import { eq } from "drizzle-orm";

// server-only throws outside Next.js; stub it.
mock.module("server-only", () => ({}));
// unstable_cache would memoize across cases; pass-through so every call reads
// fresh from the DB (both isAddonEnabled's row cache and getOrgBillingStatus).
mock.module("next/cache", () => ({
  unstable_cache: (fn: unknown) => fn,
  revalidateTag: () => {},
  updateTag: () => {},
}));

const RUN_DB = process.env.DB_TESTS === "1";
const MCP_ADDON = "checklist_mcp";
const BYOK_ADDON = "seranking_byok";

describe.skipIf(!RUN_DB)("mcp entitlements (postgres)", () => {
  let db: typeof import("@/lib/db/client").db;
  let schema: typeof import("@/lib/db/domain-schema");
  let authSchema: typeof import("@/lib/db/auth-schema");

  const PAID_ORG = "ent-paid-org"; // has an org_addons row (paid plan / god-mode)
  const TRIAL_ORG = "ent-trial-org"; // no row, app-level trial in progress
  const EXPIRED_ORG = "ent-expired-org"; // no row, no trial, no sub
  const ACTIVE_ORG = "ent-active-org"; // no row, active Stripe sub
  const ALL_ORGS = [PAID_ORG, TRIAL_ORG, EXPIRED_ORG, ACTIVE_ORG];

  async function ensureOrg(id: string, trialEndsAt: Date | null) {
    await db
      .insert(authSchema.organization)
      .values({ id, name: id, slug: id, createdAt: new Date(), trialEndsAt })
      .onConflictDoNothing();
  }

  beforeEach(async () => {
    ({ db } = await import("@/lib/db/client"));
    schema = await import("@/lib/db/domain-schema");
    authSchema = await import("@/lib/db/auth-schema");
    const { assertTestDb } = await import("@/lib/db/assert-test-db");
    await assertTestDb();

    for (const id of ALL_ORGS) {
      await db.delete(schema.orgAddons).where(eq(schema.orgAddons.orgId, id));
      await db
        .delete(authSchema.subscription)
        .where(eq(authSchema.subscription.referenceId, id));
      await db
        .delete(authSchema.organization)
        .where(eq(authSchema.organization.id, id));
    }

    const future = new Date(Date.now() + 7 * 24 * 3600 * 1000);
    await ensureOrg(PAID_ORG, null);
    await ensureOrg(TRIAL_ORG, future);
    await ensureOrg(EXPIRED_ORG, null);
    await ensureOrg(ACTIVE_ORG, null);

    // Paid / god-mode org: the entitlement row is present.
    await db
      .insert(schema.orgAddons)
      .values({ orgId: PAID_ORG, addon: MCP_ADDON })
      .onConflictDoNothing();

    // Active org: an access-granting Stripe subscription, but NO org_addons row
    // (its plan doesn't include the MCP add-on).
    await db
      .insert(authSchema.subscription)
      .values({
        id: `${ACTIVE_ORG}-sub`,
        plan: "pro",
        referenceId: ACTIVE_ORG,
        status: "active",
        periodStart: new Date(),
      })
      .onConflictDoNothing();
  });

  test("org with an org_addons row → MCP add-on enabled", async () => {
    const { isAddonEnabled } = await import("./entitlements");
    expect(await isAddonEnabled(PAID_ORG, MCP_ADDON)).toBe(true);
  });

  test("org without a row but in an app-level trial → MCP add-on enabled (derived)", async () => {
    const { isAddonEnabled } = await import("./entitlements");
    expect(await isAddonEnabled(TRIAL_ORG, MCP_ADDON)).toBe(true);
    // The trial access is computed, never stored: no row must have been posted.
    const rows = await db
      .select()
      .from(schema.orgAddons)
      .where(eq(schema.orgAddons.orgId, TRIAL_ORG));
    expect(rows.length).toBe(0);
  });

  test("org without a row and expired (no trial, no sub) → MCP add-on disabled", async () => {
    const { isAddonEnabled } = await import("./entitlements");
    expect(await isAddonEnabled(EXPIRED_ORG, MCP_ADDON)).toBe(false);
  });

  test("org without a row but with an active sub → MCP add-on disabled (only a row grants a paid org)", async () => {
    const { isAddonEnabled } = await import("./entitlements");
    expect(await isAddonEnabled(ACTIVE_ORG, MCP_ADDON)).toBe(false);
  });

  test("trial opens ONLY the MCP add-on — seranking_byok stays row-only", async () => {
    const { isAddonEnabled } = await import("./entitlements");
    // Trialing org, no seranking_byok row → the BYOK add-on stays closed.
    expect(await isAddonEnabled(TRIAL_ORG, BYOK_ADDON)).toBe(false);
  });
});
