// Unit + integration tests. The unit block below runs unconditionally; the
// integration block is gated on DB_TESTS=1, against the *_test DB only.
import { beforeEach, describe, expect, mock, test } from "bun:test";
import { shouldBootstrapOrg } from "./sys-account";

mock.module("server-only", () => ({}));

describe("shouldBootstrapOrg", () => {
  test("SYS accounts never get a personal org (staff AND admin)", () => {
    expect(shouldBootstrapOrg("staff")).toBe(false);
    // Admin SYS (role "admin", stamped for SUPER_ADMIN_EMAILS) is orgless too
    // — no org, no site, /admin dash only (spec §2.bis).
    expect(shouldBootstrapOrg("admin")).toBe(false);
  });
  test("regular users do (user, null, undefined)", () => {
    expect(shouldBootstrapOrg("user")).toBe(true);
    expect(shouldBootstrapOrg(null)).toBe(true);
    expect(shouldBootstrapOrg(undefined)).toBe(true);
  });
});

const RUN_DB = process.env.DB_TESTS === "1";

describe.skipIf(!RUN_DB)("createOrgForUser (postgres)", () => {
  let db: typeof import("@/lib/db/client").db;
  let schema: typeof import("@/lib/db/auth-schema");
  let mod: typeof import("./org-bootstrap");
  const USER = "test-bootstrap-user";

  beforeEach(async () => {
    ({ db } = await import("@/lib/db/client"));
    schema = await import("@/lib/db/auth-schema");
    mod = await import("./org-bootstrap");
    const { assertTestDb } = await import("@/lib/db/assert-test-db");
    const { eq } = await import("drizzle-orm");
    await assertTestDb();
    const members = await db
      .select({ orgId: schema.member.organizationId })
      .from(schema.member)
      .where(eq(schema.member.userId, USER));
    await db.delete(schema.member).where(eq(schema.member.userId, USER));
    for (const m of members) {
      await db
        .delete(schema.organization)
        .where(eq(schema.organization.id, m.orgId));
    }
    await db.delete(schema.user).where(eq(schema.user.id, USER));
    await db.insert(schema.user).values({
      id: USER,
      name: "Test Bootstrap",
      email: "bootstrap@test.dev",
      emailVerified: true,
      createdAt: new Date(),
      updatedAt: new Date(),
    });
  });

  test("creates an organization + owner membership, returns the org id", async () => {
    const orgId = await mod.createOrgForUser(USER, "Test Bootstrap");
    const { eq } = await import("drizzle-orm");
    const [org] = await db
      .select()
      .from(schema.organization)
      .where(eq(schema.organization.id, orgId));
    expect(org).toBeDefined();
    const [m] = await db
      .select()
      .from(schema.member)
      .where(eq(schema.member.userId, USER));
    expect(m.organizationId).toBe(orgId);
    expect(m.role).toBe("owner");
  });

  test("slugs are unique across calls (no collision)", async () => {
    const a = await mod.createOrgForUser(USER, "Acme");
    const b = await mod.createOrgForUser(USER, "Acme");
    expect(a).not.toBe(b);
  });

  test("first org gets a 14-day trial; second org gets none", async () => {
    const { eq } = await import("drizzle-orm");
    const { TRIAL_DAYS } = await import("@/lib/billing/plans");

    const firstId = await mod.createOrgForUser(USER, "First Org");
    const [first] = await db
      .select({ trialEndsAt: schema.organization.trialEndsAt })
      .from(schema.organization)
      .where(eq(schema.organization.id, firstId));
    expect(first.trialEndsAt).not.toBeNull();
    const expected = Date.now() + TRIAL_DAYS * 24 * 60 * 60 * 1000;
    const FIVE_MIN = 5 * 60 * 1000;
    expect(
      Math.abs((first.trialEndsAt as Date).getTime() - expected),
    ).toBeLessThan(FIVE_MIN);

    const secondId = await mod.createOrgForUser(USER, "Second Org");
    const [second] = await db
      .select({ trialEndsAt: schema.organization.trialEndsAt })
      .from(schema.organization)
      .where(eq(schema.organization.id, secondId));
    expect(second.trialEndsAt).toBeNull();
  });
});
